@atomicmail/agent-skill 0.2.0 → 0.2.1

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 (65) hide show
  1. package/README.md +47 -12
  2. package/SKILL.md +16 -36
  3. package/esm/_dnt.polyfills.d.ts +101 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +127 -0
  6. package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
  7. package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
  8. package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
  9. package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
  10. package/esm/lib/{src → agent/jmap}/agent-help-content.js +11 -3
  11. package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
  12. package/esm/lib/{src → agent/jmap}/agent-jmap.js +47 -3
  13. package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
  14. package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
  15. package/esm/lib/agent/session/agent-resolve-config.d.ts +24 -0
  16. package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
  17. package/esm/lib/agent/session/agent-resolve-config.js +70 -0
  18. package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
  19. package/esm/lib/{src → agent/session}/agent-session.js +3 -3
  20. package/esm/lib/core/consts.d.ts.map +1 -0
  21. package/esm/lib/core/types.d.ts +2 -0
  22. package/esm/lib/core/types.d.ts.map +1 -0
  23. package/esm/lib/core/types.js +1 -0
  24. package/esm/lib/core/utils.d.ts +10 -0
  25. package/esm/lib/core/utils.d.ts.map +1 -0
  26. package/esm/lib/core/utils.js +28 -0
  27. package/esm/lib/mod.d.ts +14 -0
  28. package/esm/lib/mod.d.ts.map +1 -0
  29. package/esm/lib/mod.js +13 -0
  30. package/esm/lib/network/auth-client.d.ts +57 -0
  31. package/esm/lib/network/auth-client.d.ts.map +1 -0
  32. package/esm/lib/network/auth-client.js +188 -0
  33. package/esm/skill/cli.d.ts +3 -0
  34. package/esm/skill/cli.d.ts.map +1 -0
  35. package/esm/skill/{scripts/cli.js → cli.js} +2 -5
  36. package/package.json +4 -4
  37. package/presets/list_inbox.json +39 -0
  38. package/presets/reply.json +75 -0
  39. package/presets/send_mail.json +42 -0
  40. package/esm/lib/src/agent-auth-http.d.ts.map +0 -1
  41. package/esm/lib/src/agent-credentials-store.d.ts.map +0 -1
  42. package/esm/lib/src/agent-help-content.d.ts.map +0 -1
  43. package/esm/lib/src/agent-jmap.d.ts.map +0 -1
  44. package/esm/lib/src/agent-jwt.d.ts.map +0 -1
  45. package/esm/lib/src/agent-pow.d.ts.map +0 -1
  46. package/esm/lib/src/agent-session.d.ts.map +0 -1
  47. package/esm/lib/src/agent-vars.d.ts.map +0 -1
  48. package/esm/lib/src/consts.d.ts.map +0 -1
  49. package/esm/skill/scripts/cli.d.ts +0 -3
  50. package/esm/skill/scripts/cli.d.ts.map +0 -1
  51. /package/esm/lib/{src → agent/auth}/agent-auth-http.d.ts +0 -0
  52. /package/esm/lib/{src → agent/auth}/agent-auth-http.js +0 -0
  53. /package/esm/lib/{src → agent/auth}/agent-jwt.d.ts +0 -0
  54. /package/esm/lib/{src → agent/auth}/agent-jwt.js +0 -0
  55. /package/esm/lib/{src → agent/auth}/agent-pow.d.ts +0 -0
  56. /package/esm/lib/{src → agent/auth}/agent-pow.js +0 -0
  57. /package/esm/lib/{src → agent/jmap}/agent-help-content.d.ts +0 -0
  58. /package/esm/lib/{src → agent/jmap}/agent-jmap.d.ts +0 -0
  59. /package/esm/lib/{src → agent/jmap}/agent-vars.d.ts +0 -0
  60. /package/esm/lib/{src → agent/jmap}/agent-vars.js +0 -0
  61. /package/esm/lib/{src → agent/session}/agent-credentials-store.d.ts +0 -0
  62. /package/esm/lib/{src → agent/session}/agent-credentials-store.js +0 -0
  63. /package/esm/lib/{src → agent/session}/agent-session.d.ts +0 -0
  64. /package/esm/lib/{src → core}/consts.d.ts +0 -0
  65. /package/esm/lib/{src → core}/consts.js +0 -0
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @atomicmail/agent-skill
2
2
 
3
- Atomic Mail AgentSkill CLI for AI agents. It exposes three commands: `register`,
4
- `jmap_request`, and `help` (same surface as `@atomicmail/mcp`).
3
+ Atomic Mail AgentSkill CLI for shell-capable AI agents. It exposes three
4
+ commands: `register`, `jmap_request`, and `help`.
5
5
 
6
6
  ## Install / run
7
7
 
@@ -9,12 +9,6 @@ Atomic Mail AgentSkill CLI for AI agents. It exposes three commands: `register`,
9
9
  npx --package=@atomicmail/agent-skill atomicmail --help
10
10
  ```
11
11
 
12
- From source:
13
-
14
- ```bash
15
- deno run -A scripts/cli.ts --help
16
- ```
17
-
18
12
  ## Quick start
19
13
 
20
14
  ```bash
@@ -25,7 +19,7 @@ npx --package=@atomicmail/agent-skill atomicmail jmap_request \
25
19
  --ops '[["Mailbox/get", {"accountId": "$ACCOUNT_ID"}, "m0"]]'
26
20
  ```
27
21
 
28
- ## Placeholder substitution
22
+ ## `jmap_request` and placeholders
29
23
 
30
24
  - Built-in placeholders: `$ACCOUNT_ID`, `$INBOX`
31
25
  - Custom placeholders: any `$VAR_NAME` via `--vars '{"VAR_NAME":"value"}'`
@@ -35,10 +29,44 @@ Example:
35
29
 
36
30
  ```bash
37
31
  npx --package=@atomicmail/agent-skill atomicmail jmap_request \
38
- --ops-file send_email.json \
32
+ --ops-file send_mail.json \
39
33
  --vars '{"TO":"alice@example.com","SUBJECT":"Hello","BODY":"Hi there"}'
40
34
  ```
41
35
 
36
+ ## Presets and placeholders
37
+
38
+ Presets are reusable JSON files for `jmap_request`:
39
+
40
+ - Inline JSON: `--ops '[["Mailbox/get", {"accountId":"$ACCOUNT_ID"}, "m0"]]'`
41
+ - Preset file: `--ops-file list_inbox.json --vars '{"COUNT":"10"}'`
42
+
43
+ Resolution order for `--ops-file`:
44
+
45
+ 1. Resolve relative to `--credentials-dir` (default `~/.atomicmail`).
46
+ 2. If missing, fall back to bundled presets in the package.
47
+
48
+ Placeholder rules:
49
+
50
+ - Pattern: `$VAR_NAME`, where `VAR_NAME` matches `^[A-Z][A-Z0-9_]*$`.
51
+ - Built-ins: `$ACCOUNT_ID`, `$INBOX`.
52
+ - Lowercase `$tokens` such as JMAP back-references (`$draft`) are not matched.
53
+ - Custom placeholders: pass string values via `--vars`.
54
+ - Resolution order per variable: `--vars` first, then built-in auto-resolvers.
55
+ - Built-ins can be overridden via `--vars` using `ACCOUNT_ID` or `INBOX`.
56
+ - If any referenced variable is unresolved, `jmap_request` fails with a missing
57
+ variables error.
58
+ - Substitution is single-pass: inserted values are not scanned again for nested
59
+ `$VAR_NAME` tokens.
60
+
61
+ Bundled presets:
62
+
63
+ - `send_mail.json` (`$TO`, `$SUBJECT`, `$BODY`)
64
+ - `list_inbox.json` (`$COUNT`)
65
+ - `reply.json` (`$MAIL_ID`, `$BODY`)
66
+
67
+ `--ops-file` resolves against `--credentials-dir` first, then bundled presets
68
+ inside the package.
69
+
42
70
  ## Shared state
43
71
 
44
72
  Credential files in `~/.atomicmail` (mode `0600`):
@@ -47,10 +75,17 @@ Credential files in `~/.atomicmail` (mode `0600`):
47
75
  - `session.jwt`
48
76
  - `capability.jwt`
49
77
 
50
- The skill and MCP server share this layout.
78
+ This is the on-disk state used by the CLI (and MCP).
79
+
80
+ ## Defaults
81
+
82
+ - auth endpoint: `https://auth.atomicmail.ai`
83
+ - api endpoint: `https://api.atomicmail.ai`
84
+ - credentials directory: `~/.atomicmail`
51
85
 
52
86
  ## Overriding defaults
53
87
 
54
- - Endpoints: `--auth-url`, `--api-url` or `ATOMIC_MAIL_AUTH_URL`, `ATOMIC_MAIL_API_URL`
88
+ - Endpoints: `--auth-url`, `--api-url` or `ATOMIC_MAIL_AUTH_URL`,
89
+ `ATOMIC_MAIL_API_URL`
55
90
  - Credentials path: `--credentials-dir` or `ATOMIC_MAIL_CREDENTIALS_DIR`
56
91
  - PoW salt: `--scrypt-salt` or `ATOMIC_MAIL_SCRYPT_SALT`
package/SKILL.md CHANGED
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  name: atomicmail
3
3
  description: Read and write email through the Atomic Mail ESP from an AI agent. Handles proof-of-work authentication and JMAP so the agent thinks in JMAP method calls. Use when the user asks to register an email inbox, list mailboxes, fetch or send email.
4
- license: MIT
5
- compatibility: Requires Deno 2.0+ to run scripts directly, or Node 20+ / Bun 1.1+ via `npx @atomicmail/agent-skill` after publishing. Needs network access to the configured auth-service and api-service.
6
4
  ---
7
5
 
8
6
  # Atomic Mail
@@ -19,17 +17,10 @@ rotation. This skill ships a single CLI entrypoint with three commands:
19
17
 
20
18
  ## Commands
21
19
 
22
- All invocations use `scripts/cli.ts` or the published binary **`atomicmail`**:
23
-
24
20
  ```bash
25
- # Deno (repo)
26
- deno run -A scripts/cli.ts register --username alice
27
- deno run -A scripts/cli.ts jmap_request --ops-file x.json
28
- deno run -A scripts/cli.ts help --topic presets
29
-
30
- # Node / Bun (after publish)
31
- npx --package=@atomicmail/agent-skill atomicmail register --username "myagent" ...
32
- npx --package=@atomicmail/agent-skill atomicmail jmap_request --ops-file send_hello.json
21
+ npx --package=@atomicmail/agent-skill atomicmail register --username "myagent"
22
+
23
+ npx --package=@atomicmail/agent-skill atomicmail jmap_request --ops-file list_inbox.json --vars '{"COUNT":"10"}'
33
24
  ```
34
25
 
35
26
  Run **`atomicmail --help`** or **`atomicmail <command> --help`** for flags.
@@ -45,7 +36,7 @@ Run **`atomicmail --help`** or **`atomicmail <command> --help`** for flags.
45
36
  ### 1. Register (new account)
46
37
 
47
38
  ```bash
48
- deno run -A scripts/cli.ts register \
39
+ npx --package=@atomicmail/agent-skill atomicmail register \
49
40
  --username "alice"
50
41
  ```
51
42
 
@@ -55,14 +46,14 @@ including `inbox` and `accountId`.
55
46
  ### 2. Register (existing API key, in case losing the credentials file)
56
47
 
57
48
  ```bash
58
- deno run -A scripts/cli.ts register \
49
+ npx --package=@atomicmail/agent-skill atomicmail register \
59
50
  --api-key "..."
60
51
  ```
61
52
 
62
53
  ### 3. JMAP request
63
54
 
64
55
  ```bash
65
- deno run -A scripts/cli.ts jmap_request \
56
+ npx --package=@atomicmail/agent-skill atomicmail jmap_request \
66
57
  --ops '[["Mailbox/get", {"accountId": "$ACCOUNT_ID"}, "m0"]]'
67
58
  ```
68
59
 
@@ -73,37 +64,31 @@ strings (same substitution applies to `--ops` and `--ops-file`).
73
64
  Preset file:
74
65
 
75
66
  ```bash
76
- deno run -A scripts/cli.ts jmap_request \
67
+ npx --package=@atomicmail/agent-skill atomicmail jmap_request \
77
68
  --ops-file fetch_last_100.json
78
69
  ```
79
70
 
80
71
  With custom placeholders:
81
72
 
82
73
  ```bash
83
- deno run -A scripts/cli.ts jmap_request \
84
- --ops-file send_email.json \
74
+ npx --package=@atomicmail/agent-skill atomicmail jmap_request \
75
+ --ops-file send_mail.json \
85
76
  --vars '{"TO":"alice@example.com","SUBJECT":"Hello","BODY":"Hi there"}'
86
77
  ```
87
78
 
88
- ### 4. Help
89
-
90
- ```bash
91
- deno run -A scripts/cli.ts help
92
- deno run -A scripts/cli.ts help --topic jmap_cheatsheet
93
- ```
79
+ Bundled presets (no local file creation required):
94
80
 
95
- ## npm package
81
+ - `send_mail.json` (`$TO`, `$SUBJECT`, `$BODY`)
82
+ - `list_inbox.json` (`$COUNT`)
83
+ - `reply.json` (`$MAIL_ID`, `$BODY`)
96
84
 
97
- From the `skill/` directory:
85
+ ### 4. Help
98
86
 
99
87
  ```bash
100
- deno task build:npm
101
- cd npm && npm publish --access public
88
+ npx --package=@atomicmail/agent-skill atomicmail help
89
+ npx --package=@atomicmail/agent-skill atomicmail help --topic jmap_cheatsheet
102
90
  ```
103
91
 
104
- The published **`atomicmail`** binary exposes `register`, `jmap_request`, and
105
- `help`.
106
-
107
92
  ## Security
108
93
 
109
94
  - `credentials.json` holds the API key (mode `0600`). Do not commit it.
@@ -115,8 +100,3 @@ The published **`atomicmail`** binary exposes `register`, `jmap_request`, and
115
100
  `ATOMIC_MAIL_API_URL`
116
101
  - Credentials path: `--credentials-dir` or `ATOMIC_MAIL_CREDENTIALS_DIR`
117
102
  - PoW salt: `--scrypt-salt` or `ATOMIC_MAIL_SCRYPT_SALT`
118
-
119
- ## Building
120
-
121
- See repository [`AGENTS.md`](../AGENTS.md) for formatting (`deno fmt`) and
122
- conventions.
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Based on [import-meta-ponyfill](https://github.com/gaubee/import-meta-ponyfill),
3
+ * but instead of using npm to install additional dependencies,
4
+ * this approach manually consolidates cjs/mjs/d.ts into a single file.
5
+ *
6
+ * Note that this code might be imported multiple times
7
+ * (for example, both dnt.test.polyfills.ts and dnt.polyfills.ts contain this code;
8
+ * or Node.js might dynamically clear the cache and then force a require).
9
+ * Therefore, it's important to avoid redundant writes to global objects.
10
+ * Additionally, consider that commonjs is used alongside esm,
11
+ * so the two ponyfill functions are stored independently in two separate global objects.
12
+ */
13
+ import { createRequire } from "node:module";
14
+ import { type URL } from "node:url";
15
+ declare global {
16
+ interface ImportMeta {
17
+ /** A string representation of the fully qualified module URL. When the
18
+ * module is loaded locally, the value will be a file URL (e.g.
19
+ * `file:///path/module.ts`).
20
+ *
21
+ * You can also parse the string as a URL to determine more information about
22
+ * how the current module was loaded. For example to determine if a module was
23
+ * local or not:
24
+ *
25
+ * ```ts
26
+ * const url = new URL(import.meta.url);
27
+ * if (url.protocol === "file:") {
28
+ * console.log("this module was loaded locally");
29
+ * }
30
+ * ```
31
+ */
32
+ url: string;
33
+ /**
34
+ * A function that returns resolved specifier as if it would be imported
35
+ * using `import(specifier)`.
36
+ *
37
+ * ```ts
38
+ * console.log(import.meta.resolve("./foo.js"));
39
+ * // file:///dev/foo.js
40
+ * ```
41
+ *
42
+ * @param specifier The module specifier to resolve relative to `parent`.
43
+ * @param parent The absolute parent module URL to resolve from.
44
+ * @returns The absolute (`file:`) URL string for the resolved module.
45
+ */
46
+ resolve(specifier: string, parent?: string | URL | undefined): string;
47
+ /** A flag that indicates if the current module is the main module that was
48
+ * called when starting the program under Deno.
49
+ *
50
+ * ```ts
51
+ * if (import.meta.main) {
52
+ * // this was loaded as the main module, maybe do some bootstrapping
53
+ * }
54
+ * ```
55
+ */
56
+ main: boolean;
57
+ /** The absolute path of the current module.
58
+ *
59
+ * This property is only provided for local modules (ie. using `file://` URLs).
60
+ *
61
+ * Example:
62
+ * ```
63
+ * // Unix
64
+ * console.log(import.meta.filename); // /home/alice/my_module.ts
65
+ *
66
+ * // Windows
67
+ * console.log(import.meta.filename); // C:\alice\my_module.ts
68
+ * ```
69
+ */
70
+ filename: string;
71
+ /** The absolute path of the directory containing the current module.
72
+ *
73
+ * This property is only provided for local modules (ie. using `file://` URLs).
74
+ *
75
+ * * Example:
76
+ * ```
77
+ * // Unix
78
+ * console.log(import.meta.dirname); // /home/alice
79
+ *
80
+ * // Windows
81
+ * console.log(import.meta.dirname); // C:\alice
82
+ * ```
83
+ */
84
+ dirname: string;
85
+ }
86
+ }
87
+ type NodeRequest = ReturnType<typeof createRequire>;
88
+ type NodeModule = NonNullable<NodeRequest["main"]>;
89
+ interface ImportMetaPonyfillCommonjs {
90
+ (require: NodeRequest, module: NodeModule): ImportMeta;
91
+ }
92
+ interface ImportMetaPonyfillEsmodule {
93
+ (importMeta: ImportMeta): ImportMeta;
94
+ }
95
+ interface ImportMetaPonyfill extends ImportMetaPonyfillCommonjs, ImportMetaPonyfillEsmodule {
96
+ }
97
+ export declare let import_meta_ponyfill_commonjs: ImportMetaPonyfillCommonjs;
98
+ export declare let import_meta_ponyfill_esmodule: ImportMetaPonyfillEsmodule;
99
+ export declare let import_meta_ponyfill: ImportMetaPonyfill;
100
+ export {};
101
+ //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAgC,KAAK,GAAG,EAAE,MAAM,UAAU,CAAC;AAGlE,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,UAAU;QAClB;;;;;;;;;;;;;;WAcG;QACH,GAAG,EAAE,MAAM,CAAC;QACZ;;;;;;;;;;;;WAYG;QACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,SAAS,GAAG,MAAM,CAAC;QACtE;;;;;;;;WAQG;QACH,IAAI,EAAE,OAAO,CAAC;QAEd;;;;;;;;;;;;WAYG;QACH,QAAQ,EAAE,MAAM,CAAC;QAEjB;;;;;;;;;;;;WAYG;QACH,OAAO,EAAE,MAAM,CAAC;KACjB;CACF;AAED,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,KAAK,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,UAAU,0BAA0B;IAClC,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACxD;AACD,UAAU,0BAA0B;IAClC,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAAC;CACtC;AACD,UAAU,kBACR,SAAQ,0BAA0B,EAAE,0BAA0B;CAC/D;AAiBD,eAAO,IAAI,6BAA6B,EA2BnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,6BAA6B,EA4DnC,0BAA0B,CAAC;AAMhC,eAAO,IAAI,oBAAoB,EAoB1B,kBAAkB,CAAC"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Based on [import-meta-ponyfill](https://github.com/gaubee/import-meta-ponyfill),
3
+ * but instead of using npm to install additional dependencies,
4
+ * this approach manually consolidates cjs/mjs/d.ts into a single file.
5
+ *
6
+ * Note that this code might be imported multiple times
7
+ * (for example, both dnt.test.polyfills.ts and dnt.polyfills.ts contain this code;
8
+ * or Node.js might dynamically clear the cache and then force a require).
9
+ * Therefore, it's important to avoid redundant writes to global objects.
10
+ * Additionally, consider that commonjs is used alongside esm,
11
+ * so the two ponyfill functions are stored independently in two separate global objects.
12
+ */
13
+ //@ts-ignore
14
+ import { createRequire } from "node:module";
15
+ //@ts-ignore
16
+ import { fileURLToPath, pathToFileURL } from "node:url";
17
+ //@ts-ignore
18
+ import { dirname } from "node:path";
19
+ const defineGlobalPonyfill = (symbolFor, fn) => {
20
+ if (!Reflect.has(globalThis, Symbol.for(symbolFor))) {
21
+ Object.defineProperty(globalThis, Symbol.for(symbolFor), {
22
+ configurable: true,
23
+ get() {
24
+ return fn;
25
+ },
26
+ });
27
+ }
28
+ };
29
+ export let import_meta_ponyfill_commonjs = (Reflect.get(globalThis, Symbol.for("import-meta-ponyfill-commonjs")) ??
30
+ (() => {
31
+ const moduleImportMetaWM = new WeakMap();
32
+ return (require, module) => {
33
+ let importMetaCache = moduleImportMetaWM.get(module);
34
+ if (importMetaCache == null) {
35
+ const importMeta = Object.assign(Object.create(null), {
36
+ url: pathToFileURL(module.filename).href,
37
+ main: require.main == module,
38
+ resolve: (specifier, parentURL = importMeta.url) => {
39
+ return pathToFileURL((importMeta.url === parentURL
40
+ ? require
41
+ : createRequire(parentURL))
42
+ .resolve(specifier)).href;
43
+ },
44
+ filename: module.filename,
45
+ dirname: module.path,
46
+ });
47
+ moduleImportMetaWM.set(module, importMeta);
48
+ importMetaCache = importMeta;
49
+ }
50
+ return importMetaCache;
51
+ };
52
+ })());
53
+ defineGlobalPonyfill("import-meta-ponyfill-commonjs", import_meta_ponyfill_commonjs);
54
+ export let import_meta_ponyfill_esmodule = (Reflect.get(globalThis, Symbol.for("import-meta-ponyfill-esmodule")) ??
55
+ ((importMeta) => {
56
+ const resolveFunStr = String(importMeta.resolve);
57
+ const shimWs = new WeakSet();
58
+ //@ts-ignore
59
+ const mainUrl = ("file:///" + process.argv[1].replace(/\\/g, "/"))
60
+ .replace(/\/{3,}/, "///");
61
+ const commonShim = (importMeta) => {
62
+ if (typeof importMeta.main !== "boolean") {
63
+ importMeta.main = importMeta.url === mainUrl;
64
+ }
65
+ if (typeof importMeta.filename !== "string") {
66
+ importMeta.filename = fileURLToPath(importMeta.url);
67
+ importMeta.dirname = dirname(importMeta.filename);
68
+ }
69
+ };
70
+ if (
71
+ // v16.2.0+, v14.18.0+: Add support for WHATWG URL object to parentURL parameter.
72
+ resolveFunStr === "undefined" ||
73
+ // v20.0.0+, v18.19.0+"" This API now returns a string synchronously instead of a Promise.
74
+ resolveFunStr.startsWith("async")
75
+ // enable by --experimental-import-meta-resolve flag
76
+ ) {
77
+ import_meta_ponyfill_esmodule = (importMeta) => {
78
+ if (!shimWs.has(importMeta)) {
79
+ shimWs.add(importMeta);
80
+ const importMetaUrlRequire = {
81
+ url: importMeta.url,
82
+ require: createRequire(importMeta.url),
83
+ };
84
+ importMeta.resolve = function resolve(specifier, parentURL = importMeta.url) {
85
+ return pathToFileURL((importMetaUrlRequire.url === parentURL
86
+ ? importMetaUrlRequire.require
87
+ : createRequire(parentURL)).resolve(specifier)).href;
88
+ };
89
+ commonShim(importMeta);
90
+ }
91
+ return importMeta;
92
+ };
93
+ }
94
+ else {
95
+ /// native support
96
+ import_meta_ponyfill_esmodule = (importMeta) => {
97
+ if (!shimWs.has(importMeta)) {
98
+ shimWs.add(importMeta);
99
+ commonShim(importMeta);
100
+ }
101
+ return importMeta;
102
+ };
103
+ }
104
+ return import_meta_ponyfill_esmodule(importMeta);
105
+ }));
106
+ defineGlobalPonyfill("import-meta-ponyfill-esmodule", import_meta_ponyfill_esmodule);
107
+ export let import_meta_ponyfill = ((...args) => {
108
+ const _MODULE = (() => {
109
+ if (typeof require === "function" && typeof module === "object") {
110
+ return "commonjs";
111
+ }
112
+ else {
113
+ // eval("typeof import.meta");
114
+ return "esmodule";
115
+ }
116
+ })();
117
+ if (_MODULE === "commonjs") {
118
+ //@ts-ignore
119
+ import_meta_ponyfill = (r, m) => import_meta_ponyfill_commonjs(r, m);
120
+ }
121
+ else {
122
+ //@ts-ignore
123
+ import_meta_ponyfill = (im) => import_meta_ponyfill_esmodule(im);
124
+ }
125
+ //@ts-ignore
126
+ return import_meta_ponyfill(...args);
127
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-auth-http.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/auth/agent-auth-http.ts"],"names":[],"mappings":"AAoCA,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAqBD;AAED,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IACJ,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GACA,OAAO,CAAC,eAAe,CAAC,CAS1B;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,eAAe,CAAC,CAgB1B"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-jwt.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/auth/agent-jwt.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc,QAAqB,CAAC;AACjD,eAAO,MAAM,iBAAiB,QAAgB,CAAC;AAE/C,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,CAc/D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAQnE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-pow.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/auth/agent-pow.ts"],"names":[],"mappings":"AAuCA,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GACnC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAU5C"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-help-content.d.ts","sourceRoot":"","sources":["../../../../src/lib/agent/jmap/agent-help-content.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA+O9C,CAAC;AAEF,eAAO,MAAM,eAAe,UAA2B,CAAC;AAExD,wBAAgB,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAW9C"}
@@ -51,7 +51,8 @@ presets, troubleshooting.`,
51
51
  \`\`\`bash
52
52
  npx --package=@atomicmail/agent-skill atomicmail register --username "myagent"
53
53
  npx --package=@atomicmail/agent-skill atomicmail jmap_request \\
54
- --ops-file send_hello.json
54
+ --ops-file list_inbox.json \\
55
+ --vars '{"COUNT":"10"}'
55
56
  npx --package=@atomicmail/agent-skill atomicmail help
56
57
  \`\`\`
57
58
 
@@ -180,8 +181,15 @@ troubleshooting.`,
180
181
  Save a method-call array or a full \`{ "using", "methodCalls" }\` envelope
181
182
  as JSON, then pass \`ops_file\` (MCP) or \`--ops-file\` (skill).
182
183
 
183
- Relative paths resolve against the credential directory (MCP) or current
184
- \`--credentials-dir\` (skill).
184
+ Relative paths first resolve against the credential directory (MCP) or current
185
+ \`--credentials-dir\` (skill). If not found, the runtime falls back to bundled
186
+ presets that ship in both npm packages.
187
+
188
+ ## Bundled presets
189
+
190
+ - \`send_mail.json\` — sends one email using \`$TO\`, \`$SUBJECT\`, \`$BODY\`.
191
+ - \`list_inbox.json\` — returns the latest \`$COUNT\` inbox messages.
192
+ - \`reply.json\` — replies in-thread using \`$MAIL_ID\` and \`$BODY\`.
185
193
 
186
194
  ## Placeholders
187
195
 
@@ -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,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;CAClC;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,CA4C5D;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 { readCredentials } from "./agent-credentials-store.js";
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
- return await readFile(filePath, "utf-8");
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"];
@@ -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;CACpB;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,CAiCxE;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,24 @@
1
+ import { type SkillFiles } from "./agent-credentials-store.js";
2
+ export type ConfigSource = "credentials-file" | "env" | "mixed" | "incomplete";
3
+ export interface ResolvedAgentConfig {
4
+ authUrl: string;
5
+ apiUrl: string;
6
+ scryptSalt: string;
7
+ apiKey?: string;
8
+ inboxId?: string;
9
+ credentialDir: string;
10
+ files: SkillFiles;
11
+ source: ConfigSource;
12
+ }
13
+ /**
14
+ * Default credential directory:
15
+ * 1. ATOMIC_MAIL_CREDENTIALS_DIR
16
+ * 2. ~/.atomicmail/ or %USERPROFILE%/.atomicmail
17
+ */
18
+ export declare function resolveCredentialDir(): string;
19
+ /**
20
+ * Merge credentials.json with ATOMIC_MAIL_* env (env wins per field).
21
+ * authUrl and apiUrl must resolve from at least one source.
22
+ */
23
+ export declare function resolveAgentConfigFromEnv(): Promise<ResolvedAgentConfig>;
24
+ //# sourceMappingURL=agent-resolve-config.d.ts.map
@@ -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"}
@@ -0,0 +1,70 @@
1
+ // Resolve MCP / process credential dir + URLs from env + credentials.json.
2
+ import process from "node:process";
3
+ import { DEFAULT_POW_SCRYPT_SALT_HEX } from "../../core/consts.js";
4
+ import { defaultFilesFromOutDir, tryReadCredentials, } from "./agent-credentials-store.js";
5
+ /**
6
+ * Default credential directory:
7
+ * 1. ATOMIC_MAIL_CREDENTIALS_DIR
8
+ * 2. ~/.atomicmail/ or %USERPROFILE%/.atomicmail
9
+ */
10
+ export function resolveCredentialDir() {
11
+ const fromEnv = process.env.ATOMIC_MAIL_CREDENTIALS_DIR;
12
+ if (fromEnv && fromEnv.length > 0)
13
+ return fromEnv;
14
+ const home = process.env.HOME || process.env.USERPROFILE;
15
+ if (!home) {
16
+ throw new Error("Cannot determine default credential directory: HOME and USERPROFILE " +
17
+ "are both unset. Set ATOMIC_MAIL_CREDENTIALS_DIR explicitly.");
18
+ }
19
+ return `${home.replace(/[\\/]+$/, "")}/.atomicmail`;
20
+ }
21
+ /**
22
+ * Merge credentials.json with ATOMIC_MAIL_* env (env wins per field).
23
+ * authUrl and apiUrl must resolve from at least one source.
24
+ */
25
+ export async function resolveAgentConfigFromEnv() {
26
+ const credentialDir = resolveCredentialDir();
27
+ const files = defaultFilesFromOutDir(credentialDir);
28
+ const fileCreds = await tryReadCredentials(files.credentialsFile);
29
+ const env = process.env;
30
+ const envAuthUrl = env.ATOMIC_MAIL_AUTH_URL;
31
+ const envApiUrl = env.ATOMIC_MAIL_API_URL;
32
+ const envSalt = env.ATOMIC_MAIL_SCRYPT_SALT;
33
+ const envApiKey = env.ATOMIC_MAIL_API_KEY;
34
+ const authUrl = envAuthUrl ?? fileCreds?.authUrl;
35
+ const apiUrl = envApiUrl ?? fileCreds?.apiUrl;
36
+ const scryptSalt = envSalt ?? fileCreds?.scryptSalt ??
37
+ DEFAULT_POW_SCRYPT_SALT_HEX;
38
+ const apiKey = envApiKey ?? fileCreds?.apiKey;
39
+ const inboxId = fileCreds?.inboxId;
40
+ const missing = [];
41
+ if (!authUrl)
42
+ missing.push("ATOMIC_MAIL_AUTH_URL");
43
+ if (!apiUrl)
44
+ missing.push("ATOMIC_MAIL_API_URL");
45
+ if (missing.length > 0) {
46
+ throw new Error(`Missing required configuration: ${missing.join(", ")}. ` +
47
+ `Provide these via environment variables, or place a populated ` +
48
+ `credentials.json in '${credentialDir}' (run register first, or set ` +
49
+ `ATOMIC_MAIL_CREDENTIALS_DIR).`);
50
+ }
51
+ const usingFile = fileCreds !== undefined;
52
+ const usingEnv = !!(envAuthUrl || envApiUrl || envSalt || envApiKey);
53
+ const source = usingFile && usingEnv
54
+ ? "mixed"
55
+ : usingFile
56
+ ? "credentials-file"
57
+ : usingEnv
58
+ ? "env"
59
+ : "incomplete";
60
+ return {
61
+ authUrl: authUrl.replace(/\/+$/, ""),
62
+ apiUrl: apiUrl.replace(/\/+$/, ""),
63
+ scryptSalt: scryptSalt,
64
+ apiKey,
65
+ inboxId,
66
+ credentialDir,
67
+ files,
68
+ source,
69
+ };
70
+ }