@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.
Files changed (82) hide show
  1. package/README.md +200 -84
  2. package/esm/_dnt.polyfills.d.ts +101 -0
  3. package/esm/_dnt.polyfills.d.ts.map +1 -0
  4. package/esm/_dnt.polyfills.js +127 -0
  5. package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
  6. package/esm/lib/agent/auth/agent-auth-http.js +85 -0
  7. package/esm/lib/{src → agent/auth}/agent-jwt.d.ts +0 -2
  8. package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
  9. package/esm/lib/{src → agent/auth}/agent-jwt.js +0 -2
  10. package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
  11. package/esm/lib/{src → agent/jmap}/agent-help-content.d.ts +1 -0
  12. package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
  13. package/esm/lib/{src → agent/jmap}/agent-help-content.js +46 -19
  14. package/esm/lib/{src → agent/jmap}/agent-jmap.d.ts +7 -0
  15. package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
  16. package/esm/lib/{src → agent/jmap}/agent-jmap.js +63 -3
  17. package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
  18. package/esm/lib/{src → agent/session}/agent-credentials-store.d.ts +2 -0
  19. package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
  20. package/esm/lib/{src → agent/session}/agent-credentials-store.js +2 -0
  21. package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
  22. package/esm/lib/{src → agent/session}/agent-resolve-config.js +1 -1
  23. package/esm/lib/{src → agent/session}/agent-session.d.ts +5 -0
  24. package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
  25. package/esm/lib/{src → agent/session}/agent-session.js +46 -10
  26. package/esm/lib/core/consts.d.ts.map +1 -0
  27. package/esm/lib/core/read-npm-package-readme.d.ts +6 -0
  28. package/esm/lib/core/read-npm-package-readme.d.ts.map +1 -0
  29. package/esm/lib/core/read-npm-package-readme.js +66 -0
  30. package/esm/lib/core/types.d.ts +2 -0
  31. package/esm/lib/core/types.d.ts.map +1 -0
  32. package/esm/lib/core/types.js +1 -0
  33. package/esm/lib/core/utils.d.ts +10 -0
  34. package/esm/lib/core/utils.d.ts.map +1 -0
  35. package/esm/lib/core/utils.js +28 -0
  36. package/esm/lib/mod.d.ts +15 -0
  37. package/esm/lib/mod.d.ts.map +1 -0
  38. package/esm/lib/mod.js +14 -0
  39. package/esm/lib/network/auth-client.d.ts +57 -0
  40. package/esm/lib/network/auth-client.d.ts.map +1 -0
  41. package/esm/lib/network/auth-client.js +211 -0
  42. package/esm/mcp/main.d.ts +3 -0
  43. package/esm/mcp/main.d.ts.map +1 -0
  44. package/esm/mcp/{src/main.js → main.js} +4 -3
  45. package/esm/mcp/tools/help.d.ts.map +1 -0
  46. package/esm/mcp/tools/help.js +45 -0
  47. package/esm/mcp/{src/tools → tools}/jmap.d.ts +1 -1
  48. package/esm/mcp/tools/jmap.d.ts.map +1 -0
  49. package/esm/mcp/{src/tools → tools}/jmap.js +5 -4
  50. package/esm/mcp/{src/tools → tools}/register.d.ts +1 -1
  51. package/esm/mcp/tools/register.d.ts.map +1 -0
  52. package/package.json +5 -5
  53. package/presets/list_inbox.json +39 -0
  54. package/presets/reply.json +75 -0
  55. package/presets/send_mail.json +42 -0
  56. package/esm/lib/src/agent-auth-http.d.ts.map +0 -1
  57. package/esm/lib/src/agent-auth-http.js +0 -76
  58. package/esm/lib/src/agent-credentials-store.d.ts.map +0 -1
  59. package/esm/lib/src/agent-help-content.d.ts.map +0 -1
  60. package/esm/lib/src/agent-jmap.d.ts.map +0 -1
  61. package/esm/lib/src/agent-jwt.d.ts.map +0 -1
  62. package/esm/lib/src/agent-pow.d.ts.map +0 -1
  63. package/esm/lib/src/agent-resolve-config.d.ts.map +0 -1
  64. package/esm/lib/src/agent-session.d.ts.map +0 -1
  65. package/esm/lib/src/agent-vars.d.ts.map +0 -1
  66. package/esm/lib/src/consts.d.ts.map +0 -1
  67. package/esm/mcp/src/main.d.ts +0 -3
  68. package/esm/mcp/src/main.d.ts.map +0 -1
  69. package/esm/mcp/src/tools/help.d.ts.map +0 -1
  70. package/esm/mcp/src/tools/help.js +0 -22
  71. package/esm/mcp/src/tools/jmap.d.ts.map +0 -1
  72. package/esm/mcp/src/tools/register.d.ts.map +0 -1
  73. /package/esm/lib/{src → agent/auth}/agent-auth-http.d.ts +0 -0
  74. /package/esm/lib/{src → agent/auth}/agent-pow.d.ts +0 -0
  75. /package/esm/lib/{src → agent/auth}/agent-pow.js +0 -0
  76. /package/esm/lib/{src → agent/jmap}/agent-vars.d.ts +0 -0
  77. /package/esm/lib/{src → agent/jmap}/agent-vars.js +0 -0
  78. /package/esm/lib/{src → agent/session}/agent-resolve-config.d.ts +0 -0
  79. /package/esm/lib/{src → core}/consts.d.ts +0 -0
  80. /package/esm/lib/{src → core}/consts.js +0 -0
  81. /package/esm/mcp/{src/tools → tools}/help.d.ts +0 -0
  82. /package/esm/mcp/{src/tools → tools}/register.js +0 -0
package/README.md CHANGED
@@ -1,70 +1,233 @@
1
+ ---
2
+ description: Install and configure the @atomicmail/mcp stdio server, tools (register, jmap_request, help), and host-specific notes for chat-based agents.
3
+ ---
4
+
1
5
  # @atomicmail/mcp
2
6
 
3
7
  Atomic Mail MCP server — a local stdio Model Context Protocol server that gives
4
8
  an AI agent a programmable email inbox over JMAP, with automatic Proof-of-Work
5
9
  auth and capability-token rotation.
6
10
 
7
- The server is authored in TypeScript on Deno and built with
8
- [`dnt`](https://jsr.io/@deno/dnt) into a Node-compatible npm package, so the
9
- **same source** runs unchanged on Deno, Node, and Bun.
11
+ ## Install
10
12
 
11
- It is the MCP companion to
12
- [`@atomicmail/agent-skill`](https://www.npmjs.com/package/@atomicmail/agent-skill)
13
- — a CLI with identical credential semantics. The MCP and the skill share the
14
- same on-disk layout (`credentials.json` + `session.jwt` + `capability.jwt`).
13
+ ```json
14
+ // mcp.json
15
+
16
+ {
17
+ "mcpServers": {
18
+ "atomicmail": {
19
+ "command": "npx",
20
+ "args": ["-y", "@atomicmail/mcp"]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ Your MCP host spawns this process; see configuration below.
15
27
 
16
28
  ## Tools exposed
17
29
 
18
- | Tool | Description |
19
- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
20
- | `register` | PoW signup; persists credentials. Idempotent when username matches inbox. |
21
- | `jmap_request` | JMAP batch via `ops` or `ops_file`. Uppercase `$VAR_NAME` tokens are substituted (`$ACCOUNT_ID` / `$INBOX` from session; others via optional `vars` map). |
22
- | `help` | Built-in docs (`topic` optional). |
30
+ | Tool | Description |
31
+ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32
+ | `register` | PoW signup; persists credentials. Idempotent when username matches inbox. |
33
+ | `jmap_request` | JMAP batch via `ops` or `ops_file`. Uppercase `$VAR_NAME` tokens are substituted (`$ACCOUNT_ID` / `$INBOX` / `$UPLOAD_URL` / `$DOWNLOAD_URL` from session; others via optional `vars` map). |
34
+ | `help` | Built-in docs (`topic` optional); use `topic: "readme"` for the published package `README.md`. |
23
35
 
24
- ## Install
36
+ ## Typical MCP workflow
25
37
 
26
- ```bash
27
- npx -y @atomicmail/mcp
28
- bunx @atomicmail/mcp
29
- deno run -A npm:@atomicmail/mcp/atomicmail-mcp
30
- ```
38
+ 1. Call `register` with a username (or rely on existing `credentials.json`).
39
+ 2. `jmap_request` with `ops` or `ops_file` (optional `vars` for `$TO`,
40
+ `$SUBJECT`, etc.).
41
+ 3. `help` when stuck.
31
42
 
32
- Your MCP host spawns this process; see configuration below.
43
+ ## `jmap_request` input patterns
33
44
 
34
- ## Defaults
45
+ `jmap_request` accepts either:
35
46
 
36
- - auth endpoint: `https://auth.atomicmail.ai`
37
- - api endpoint: `https://api.atomicmail.ai`
38
- - credentials directory: `~/.atomicmail`
47
+ - inline `ops` (JMAP methodCalls array), or
48
+ - `ops_file` (JSON file path)
49
+
50
+ When using `ops_file`, relative paths first resolve against the credential
51
+ directory. If a file is not present there, the runtime falls back to bundled
52
+ presets shipped in the npm package.
53
+
54
+ ## Presets and placeholders
55
+
56
+ Presets are reusable JSON files for `jmap_request` batches:
57
+
58
+ - Inline JSON: `{"ops":[...],"vars":{"COUNT":"10"}}`
59
+ - Preset file: `{"ops_file":"list_inbox.json","vars":{"COUNT":"10"}}`
60
+
61
+ Resolution order for `ops_file`:
62
+
63
+ 1. Resolve relative to credentials directory (`~/.atomicmail` by default).
64
+ 2. If missing, fall back to bundled presets in the npm package.
65
+
66
+ Placeholder rules:
39
67
 
40
- ## Credential files
68
+ - Pattern: `$VAR_NAME`, where `VAR_NAME` matches `^[A-Z][A-Z0-9_]*$`.
69
+ - Built-ins: `$ACCOUNT_ID`, `$INBOX`, `$UPLOAD_URL`, `$DOWNLOAD_URL`.
70
+ - Lowercase `$tokens` such as JMAP back-references (`$draft`) are not matched.
71
+ - Custom placeholders: passed in `vars` as string values.
72
+ - Resolution order per variable: `vars` first, then built-in auto-resolvers.
73
+ - Built-ins can be overridden by providing `ACCOUNT_ID`, `INBOX`, `UPLOAD_URL`,
74
+ or `DOWNLOAD_URL` in `vars`.
75
+ - If any referenced variable is unresolved, `jmap_request` fails with a missing
76
+ variables error.
77
+ - Substitution is single-pass: inserted values are not scanned again for nested
78
+ `$VAR_NAME` tokens.
79
+
80
+ Bundled presets:
81
+
82
+ - `send_mail.json` (`$TO`, `$SUBJECT`, `$BODY`)
83
+ - `list_inbox.json` (`$COUNT`)
84
+ - `reply.json` (`$MAIL_ID`, `$BODY`)
85
+
86
+ `ops-file` resolves against credentials directory first, then bundled presets
87
+ inside the package.
88
+
89
+ Example:
90
+
91
+ `{ "ops_file": "list_inbox.json", "vars": { "COUNT": "10" } }`
92
+
93
+ ## Credential files and token lifecycle
41
94
 
42
95
  Mode `0600`:
43
96
 
44
- - `credentials.json` — `{ apiKey, inboxId, authUrl, apiUrl, scryptSalt }`
45
- - `session.jwt` 4h TTL, rotated via PoW
97
+ - `credentials.json` —
98
+ `{ apiKey, inboxId, authUrl, apiUrl, scryptSalt, uploadUrl, downloadUrl }`
99
+ - `session.jwt` — 1h TTL, rotated via PoW
46
100
  - `capability.jwt` — 2m TTL, rotated before JMAP calls
47
101
 
48
- Use **`npx atomicmail register`** (from `@atomicmail/agent-skill`) against the
49
- same directory, or the MCP `register` tool.
102
+ These files are created and rotated automatically by MCP tool calls. AgentSkill
103
+ CLI uses the same files.
104
+
105
+ During PoW auth, the challenge JWT is exchanged via `Authorization: Bearer ...`
106
+ for both `POST /api/v1/challenge` (response header) and `POST /api/v1/session`
107
+ (request header), and session JWT is read from the `POST /api/v1/session`
108
+ response header. `POST /api/v1/capability` accepts session JWT via bearer header
109
+ and returns capability JWT in the response bearer header. PoW values (`powHex`,
110
+ `nonce`) remain in the JSON body for session creation.
111
+
112
+ ## Attachments and blobs
50
113
 
51
- ## MCP host configuration examples
114
+ Two blob paths are supported:
52
115
 
53
- ### Cursor
116
+ - **RFC 9404 in-band blobs** via `Blob/upload` and `Blob/get` over
117
+ `jmap_request`.
118
+ - **RFC 8620 out-of-band blobs** via `uploadUrl` and `downloadUrl` templates
119
+ from JMAP session.
54
120
 
55
- `~/.cursor/mcp.json`:
121
+ ### Inline blob flow (RFC 9404)
122
+
123
+ Add `urn:ietf:params:jmap:blob` and upload data in the same JMAP batch:
56
124
 
57
125
  ```json
58
126
  {
59
- "mcpServers": {
60
- "atomicmail": {
61
- "command": "npx",
62
- "args": ["-y", "@atomicmail/mcp"]
63
- }
64
- }
127
+ "using": [
128
+ "urn:ietf:params:jmap:core",
129
+ "urn:ietf:params:jmap:mail",
130
+ "urn:ietf:params:jmap:submission",
131
+ "urn:ietf:params:jmap:blob"
132
+ ],
133
+ "methodCalls": [
134
+ [
135
+ "Blob/upload",
136
+ {
137
+ "accountId": "$ACCOUNT_ID",
138
+ "create": {
139
+ "b1": {
140
+ "data:asText": "Hello attachment",
141
+ "type": "text/plain"
142
+ }
143
+ }
144
+ },
145
+ "b0"
146
+ ],
147
+ [
148
+ "Email/set",
149
+ {
150
+ "accountId": "$ACCOUNT_ID",
151
+ "create": {
152
+ "m1": {
153
+ "from": [{ "email": "$INBOX" }],
154
+ "to": [{ "email": "$TO" }],
155
+ "subject": "With attachment",
156
+ "bodyValues": {
157
+ "body1": { "value": "See attachment." }
158
+ },
159
+ "textBody": [{ "partId": "body1", "type": "text/plain" }],
160
+ "attachments": [
161
+ {
162
+ "blobId": "#b1",
163
+ "type": "text/plain",
164
+ "name": "note.txt"
165
+ }
166
+ ]
167
+ }
168
+ }
169
+ },
170
+ "m0"
171
+ ],
172
+ [
173
+ "EmailSubmission/set",
174
+ {
175
+ "accountId": "$ACCOUNT_ID",
176
+ "create": { "s1": { "emailId": "#m1" } }
177
+ },
178
+ "s0"
179
+ ]
180
+ ]
65
181
  }
66
182
  ```
67
183
 
184
+ ### Separate upload/download flow (RFC 8620)
185
+
186
+ Use the templated URLs from session/credentials:
187
+
188
+ - `$UPLOAD_URL` template contains `{accountId}`.
189
+ - `$DOWNLOAD_URL` template contains `{accountId}`, `{blobId}`, `{name}`, and
190
+ `{type}`.
191
+
192
+ Example (MCP flow):
193
+
194
+ 1. Call `jmap_request` to get attachment metadata (for example `Email/get` with
195
+ `attachments`).
196
+ 2. Expand `$DOWNLOAD_URL` template with account/blob metadata and fetch bytes
197
+ via HTTP bearer auth.
198
+ 3. To upload bytes, expand `$UPLOAD_URL` with account id and POST binary content
199
+ per RFC 8620 upload endpoint.
200
+
201
+ ### Blob retrieval (RFC 9404)
202
+
203
+ For in-band retrieval, use `Blob/get`:
204
+
205
+ ```json
206
+ {
207
+ "using": [
208
+ "urn:ietf:params:jmap:core",
209
+ "urn:ietf:params:jmap:blob"
210
+ ],
211
+ "methodCalls": [
212
+ [
213
+ "Blob/get",
214
+ {
215
+ "accountId": "$ACCOUNT_ID",
216
+ "ids": ["$BLOB_ID"],
217
+ "properties": ["id", "data:asBase64", "size", "type"]
218
+ },
219
+ "g0"
220
+ ]
221
+ ]
222
+ }
223
+ ```
224
+
225
+ ## Defaults
226
+
227
+ - auth endpoint: `https://auth.atomicmail.ai`
228
+ - api endpoint: `https://api.atomicmail.ai`
229
+ - credentials directory: `~/.atomicmail`
230
+
68
231
  ## Overriding defaults
69
232
 
70
233
  ```json
@@ -84,50 +247,3 @@ same directory, or the MCP `register` tool.
84
247
  }
85
248
  }
86
249
  ```
87
-
88
- ## Typical agent workflow
89
-
90
- 1. `register` with a username (or rely on existing `credentials.json`).
91
- 2. `jmap_request` with `ops` or `ops_file` (optional `vars` for `$TO`,
92
- `$SUBJECT`, etc.).
93
- 3. `help` when stuck.
94
-
95
- ## JMAP presets (`ops_file`)
96
-
97
- Relative paths resolve against the credential directory. Example file
98
- `fetch_last_100.json` — then call `jmap_request` with
99
- `{ "ops_file": "fetch_last_100.json" }`.
100
-
101
- See `help` with topic `presets`.
102
-
103
- ## Develop
104
-
105
- ```bash
106
- deno task start
107
- deno task check
108
- deno task fmt
109
- deno task build:npm
110
- node npm/esm/mcp/src/main.js
111
- ```
112
-
113
- ### Project layout
114
-
115
- ```
116
- mcp/
117
- ├── deno.json
118
- ├── build_npm.ts
119
- ├── README.md
120
- ├── src/
121
- │ ├── main.ts
122
- │ └── tools/
123
- │ ├── register.ts
124
- │ ├── jmap.ts
125
- │ └── help.ts
126
- └── npm/ # dnt output (gitignored)
127
- ```
128
-
129
- Shared auth/JMAP logic lives in [`../lib/`](../lib/) (`AgentSession`, etc.).
130
-
131
- ## License
132
-
133
- MIT
@@ -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":"AAKA,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,CA8BD;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,CA8B1B;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAejB;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,85 @@
1
+ // auth-service HTTP: challenge → session → capability.
2
+ import { decodeJwtPayload } from "./agent-jwt.js";
3
+ import { solvePow } from "./agent-pow.js";
4
+ export async function fetchChallenge(authUrl) {
5
+ const res = await fetch(`${authUrl}/api/v1/challenge`, {
6
+ method: "POST",
7
+ });
8
+ const text = await res.text();
9
+ if (!res.ok) {
10
+ throw new Error(`auth-service /api/v1/challenge returned ${res.status}: ${text}`);
11
+ }
12
+ const challengeJWT = readBearerToken(res.headers.get("Authorization"), "Challenge response missing Authorization bearer token.");
13
+ const payload = decodeJwtPayload(challengeJWT);
14
+ if (typeof payload.jti !== "string" ||
15
+ typeof payload.difficulty !== "number") {
16
+ throw new Error("Challenge JWT payload malformed (missing jti or difficulty).");
17
+ }
18
+ return {
19
+ challengeJWT,
20
+ challenge: payload.jti,
21
+ difficulty: payload.difficulty,
22
+ };
23
+ }
24
+ export async function exchangeSession(authUrl, body) {
25
+ const { challengeJWT, ...payload } = body;
26
+ const res = await fetch(`${authUrl}/api/v1/session`, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ Authorization: `Bearer ${challengeJWT}`,
31
+ },
32
+ body: JSON.stringify(payload),
33
+ });
34
+ const text = await res.text();
35
+ if (!res.ok) {
36
+ throw new Error(`auth-service /api/v1/session returned ${res.status}: ${text}`);
37
+ }
38
+ const sessionJWT = readBearerToken(res.headers.get("Authorization"), "Session response missing Authorization bearer token.");
39
+ let data = {};
40
+ if (text.trim().length > 0) {
41
+ try {
42
+ data = JSON.parse(text);
43
+ }
44
+ catch {
45
+ throw new Error("auth-service /api/v1/session returned non-JSON body.");
46
+ }
47
+ }
48
+ return {
49
+ sessionJWT,
50
+ apiKey: typeof data.apiKey === "string" ? data.apiKey : undefined,
51
+ };
52
+ }
53
+ export async function fetchCapability(authUrl, sessionJWT) {
54
+ const res = await fetch(`${authUrl}/api/v1/capability`, {
55
+ method: "POST",
56
+ headers: { Authorization: `Bearer ${sessionJWT}` },
57
+ });
58
+ const text = await res.text();
59
+ if (!res.ok) {
60
+ throw new Error(`auth-service /api/v1/capability returned ${res.status}: ${text}`);
61
+ }
62
+ return readBearerToken(res.headers.get("Authorization"), "Capability response missing Authorization bearer token.");
63
+ }
64
+ export async function performPoWAndSession(input) {
65
+ const { authUrl, scryptSalt } = input;
66
+ const { challengeJWT, challenge, difficulty } = await fetchChallenge(authUrl);
67
+ const { powHex, nonce } = await solvePow(challenge, difficulty, scryptSalt, input.onPowProgress);
68
+ return exchangeSession(authUrl, {
69
+ challengeJWT,
70
+ powHex,
71
+ nonce,
72
+ apiKey: input.apiKey,
73
+ username: input.username,
74
+ });
75
+ }
76
+ function readBearerToken(headerValue, missingError) {
77
+ if (!headerValue) {
78
+ throw new Error(missingError);
79
+ }
80
+ const match = /^\s*Bearer\s+(.+?)\s*$/i.exec(headerValue);
81
+ if (!match || !match[1]) {
82
+ throw new Error("Authorization header must use Bearer scheme.");
83
+ }
84
+ return match[1];
85
+ }
@@ -1,5 +1,3 @@
1
- export declare const SESSION_TTL_MS: number;
2
- export declare const CAPABILITY_TTL_MS: number;
3
1
  export declare const SESSION_SAFETY_MARGIN_MS = 60000;
4
2
  export declare const CAPABILITY_SAFETY_MARGIN_MS = 20000;
5
3
  export interface JwtPayload {
@@ -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,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"}
@@ -1,6 +1,4 @@
1
1
  // JWT helpers for capability/session expiry checks.
2
- export const SESSION_TTL_MS = 4 * 60 * 60 * 1000;
3
- export const CAPABILITY_TTL_MS = 2 * 60 * 1000;
4
2
  export const SESSION_SAFETY_MARGIN_MS = 60_000;
5
3
  export const CAPABILITY_SAFETY_MARGIN_MS = 20_000;
6
4
  export function decodeJwtPayload(jwt) {
@@ -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"}
@@ -1,4 +1,5 @@
1
1
  export declare const HELP_TOPICS: Record<string, string>;
2
2
  export declare const HELP_TOPIC_LIST: string[];
3
+ export declare function normalizeHelpTopic(topic: string): string;
3
4
  export declare function getHelp(topic?: string): string;
4
5
  //# sourceMappingURL=agent-help-content.d.ts.map
@@ -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,CA0P9C,CAAC;AAEF,eAAO,MAAM,eAAe,UAA2B,CAAC;AAExD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAkB9C"}