@atomicmail/mcp 0.1.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.
- package/README.md +77 -187
- 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 +26 -0
- package/esm/lib/agent/auth/agent-auth-http.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-auth-http.js +76 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts +14 -0
- package/esm/lib/agent/auth/agent-jwt.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-jwt.js +29 -0
- package/esm/lib/agent/auth/agent-pow.d.ts +5 -0
- package/esm/lib/agent/auth/agent-pow.d.ts.map +1 -0
- package/esm/lib/agent/auth/agent-pow.js +49 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts +4 -0
- package/esm/lib/agent/jmap/agent-help-content.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-help-content.js +244 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts +49 -0
- package/esm/lib/agent/jmap/agent-jmap.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-jmap.js +174 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts +23 -0
- package/esm/lib/agent/jmap/agent-vars.d.ts.map +1 -0
- package/esm/lib/agent/jmap/agent-vars.js +65 -0
- package/esm/{mcp/src/credentials.d.ts → lib/agent/session/agent-credentials-store.d.ts} +3 -2
- package/esm/lib/agent/session/agent-credentials-store.d.ts.map +1 -0
- package/esm/{mcp/src/credentials.js → lib/agent/session/agent-credentials-store.js} +19 -16
- package/esm/lib/agent/session/agent-resolve-config.d.ts +24 -0
- package/esm/lib/agent/session/agent-resolve-config.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-resolve-config.js +70 -0
- package/esm/lib/agent/session/agent-session.d.ts +62 -0
- package/esm/lib/agent/session/agent-session.d.ts.map +1 -0
- package/esm/lib/agent/session/agent-session.js +206 -0
- package/esm/lib/core/consts.d.ts.map +1 -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 +14 -0
- package/esm/lib/mod.d.ts.map +1 -0
- package/esm/lib/mod.js +13 -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 +188 -0
- package/esm/mcp/main.d.ts +3 -0
- package/esm/mcp/main.d.ts.map +1 -0
- package/esm/mcp/main.js +86 -0
- package/esm/mcp/tools/help.d.ts +3 -0
- package/esm/mcp/tools/help.d.ts.map +1 -0
- package/esm/mcp/tools/help.js +22 -0
- package/esm/mcp/{src/tools → tools}/jmap.d.ts +2 -2
- package/esm/mcp/tools/jmap.d.ts.map +1 -0
- package/esm/mcp/tools/jmap.js +115 -0
- package/esm/mcp/{src/tools → tools}/register.d.ts +2 -2
- package/esm/mcp/tools/register.d.ts.map +1 -0
- package/esm/mcp/tools/register.js +43 -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/consts.d.ts.map +0 -1
- package/esm/mcp/src/auth-session.d.ts +0 -88
- package/esm/mcp/src/auth-session.d.ts.map +0 -1
- package/esm/mcp/src/auth-session.js +0 -378
- package/esm/mcp/src/credentials.d.ts.map +0 -1
- package/esm/mcp/src/docs-content.d.ts +0 -4
- package/esm/mcp/src/docs-content.d.ts.map +0 -1
- package/esm/mcp/src/docs-content.js +0 -405
- package/esm/mcp/src/main.d.ts +0 -3
- package/esm/mcp/src/main.d.ts.map +0 -1
- package/esm/mcp/src/main.js +0 -116
- package/esm/mcp/src/tools/docs.d.ts +0 -3
- package/esm/mcp/src/tools/docs.d.ts.map +0 -1
- package/esm/mcp/src/tools/docs.js +0 -22
- package/esm/mcp/src/tools/jmap.d.ts.map +0 -1
- package/esm/mcp/src/tools/jmap.js +0 -202
- package/esm/mcp/src/tools/register.d.ts.map +0 -1
- package/esm/mcp/src/tools/register.js +0 -79
- /package/esm/lib/{src → core}/consts.d.ts +0 -0
- /package/esm/lib/{src → core}/consts.js +0 -0
package/README.md
CHANGED
|
@@ -1,128 +1,108 @@
|
|
|
1
1
|
# @atomicmail/mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Atomic Mail MCP server — a local stdio Model Context Protocol server that gives
|
|
4
4
|
an AI agent a programmable email inbox over JMAP, with automatic Proof-of-Work
|
|
5
5
|
auth and capability-token rotation.
|
|
6
6
|
|
|
7
|
-
|
|
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.
|
|
7
|
+
## Install
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
```json
|
|
10
|
+
// mcp.json
|
|
11
|
+
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"atomicmail": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "@atomicmail/mcp"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Your MCP host spawns this process; see configuration below.
|
|
15
23
|
|
|
16
24
|
## Tools exposed
|
|
17
25
|
|
|
18
|
-
| Tool | Description
|
|
19
|
-
| -------------- |
|
|
20
|
-
| `register` | PoW signup
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `get_docs` | Built-in docs. Topics include `installation`, `presets`, `auth`. |
|
|
26
|
+
| Tool | Description |
|
|
27
|
+
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `register` | PoW signup; persists credentials. Idempotent when username matches inbox. |
|
|
29
|
+
| `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). |
|
|
30
|
+
| `help` | Built-in docs (`topic` optional). |
|
|
24
31
|
|
|
25
|
-
##
|
|
32
|
+
## Typical MCP workflow
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
1. Call `register` with a username (or rely on existing `credentials.json`).
|
|
35
|
+
2. `jmap_request` with `ops` or `ops_file` (optional `vars` for `$TO`,
|
|
36
|
+
`$SUBJECT`, etc.).
|
|
37
|
+
3. `help` when stuck.
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
npx -y @atomicmail/mcp
|
|
31
|
-
bunx @atomicmail/mcp
|
|
32
|
-
deno run -A npm:@atomicmail/mcp/atomicmail-mcp
|
|
33
|
-
```
|
|
39
|
+
## `jmap_request` input patterns
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
...) will spawn it for you. See the configuration section below.
|
|
41
|
+
`jmap_request` accepts either:
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
- inline `ops` (JMAP methodCalls array), or
|
|
44
|
+
- `ops_file` (JSON file path)
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
When using `ops_file`, relative paths first resolve against the credential
|
|
47
|
+
directory. If a file is not present there, the runtime falls back to bundled
|
|
48
|
+
presets shipped in the npm package.
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
`atomic-mail-signup`. Default location: `~/.atomicmail/credentials.json`.
|
|
45
|
-
Override the directory with `ATOMIC_MAIL_CREDENTIALS_DIR`.
|
|
46
|
-
2. **Environment variables.** Useful for hermetic MCP host configs:
|
|
50
|
+
## Presets and placeholders
|
|
47
51
|
|
|
48
|
-
|
|
49
|
-
| ----------------------------- | -------- | --------------------------------- |
|
|
50
|
-
| `ATOMIC_MAIL_AUTH_URL` | Yes\* | Auth service base URL |
|
|
51
|
-
| `ATOMIC_MAIL_API_URL` | Yes\* | API service / JMAP base URL |
|
|
52
|
-
| `ATOMIC_MAIL_SCRYPT_SALT` | No | Optional PoW salt override |
|
|
53
|
-
| `ATOMIC_MAIL_API_KEY` | No | Existing API key (skips signup) |
|
|
54
|
-
| `ATOMIC_MAIL_CREDENTIALS_DIR` | No | Override default credential dir |
|
|
52
|
+
Presets are reusable JSON files for `jmap_request` batches:
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
salt defaults to the built-in value that matches `auth-service`.
|
|
54
|
+
- Inline JSON: `{"ops":[...],"vars":{"COUNT":"10"}}`
|
|
55
|
+
- Preset file: `{"ops_file":"list_inbox.json","vars":{"COUNT":"10"}}`
|
|
59
56
|
|
|
60
|
-
|
|
61
|
-
startup with the missing fields listed.
|
|
57
|
+
Resolution order for `ops_file`:
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
1. Resolve relative to credentials directory (`~/.atomicmail` by default).
|
|
60
|
+
2. If missing, fall back to bundled presets in the npm package.
|
|
64
61
|
|
|
65
|
-
|
|
62
|
+
Placeholder rules:
|
|
66
63
|
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
|
|
64
|
+
- Pattern: `$VAR_NAME`, where `VAR_NAME` matches `^[A-Z][A-Z0-9_]*$`.
|
|
65
|
+
- Built-ins: `$ACCOUNT_ID`, `$INBOX`.
|
|
66
|
+
- Lowercase `$tokens` such as JMAP back-references (`$draft`) are not matched.
|
|
67
|
+
- Custom placeholders: passed in `vars` as string values.
|
|
68
|
+
- Resolution order per variable: `vars` first, then built-in auto-resolvers.
|
|
69
|
+
- Built-ins can be overridden by providing `ACCOUNT_ID` or `INBOX` in `vars`.
|
|
70
|
+
- If any referenced variable is unresolved, `jmap_request` fails with a missing
|
|
71
|
+
variables error.
|
|
72
|
+
- Substitution is single-pass: inserted values are not scanned again for nested
|
|
73
|
+
`$VAR_NAME` tokens.
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
[`@atomic-mail/agent-skill`](../../skill/) skill, you can:
|
|
75
|
+
Bundled presets:
|
|
76
76
|
|
|
77
|
-
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
see fresh JWTs as the other rotates them.
|
|
77
|
+
- `send_mail.json` (`$TO`, `$SUBJECT`, `$BODY`)
|
|
78
|
+
- `list_inbox.json` (`$COUNT`)
|
|
79
|
+
- `reply.json` (`$MAIL_ID`, `$BODY`)
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
`ops-file` resolves against credentials directory first, then bundled presets
|
|
82
|
+
inside the package.
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
Example:
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
`{ "ops_file": "list_inbox.json", "vars": { "COUNT": "10" } }`
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
{
|
|
90
|
-
"mcpServers": {
|
|
91
|
-
"atomicmail": {
|
|
92
|
-
"command": "npx",
|
|
93
|
-
"args": ["-y", "@atomicmail/mcp"],
|
|
94
|
-
"env": {
|
|
95
|
-
"ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
|
|
96
|
-
"ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
```
|
|
88
|
+
## Credential files and token lifecycle
|
|
102
89
|
|
|
103
|
-
|
|
90
|
+
Mode `0600`:
|
|
104
91
|
|
|
105
|
-
`
|
|
92
|
+
- `credentials.json` — `{ apiKey, inboxId, authUrl, apiUrl, scryptSalt }`
|
|
93
|
+
- `session.jwt` — 4h TTL, rotated via PoW
|
|
94
|
+
- `capability.jwt` — 2m TTL, rotated before JMAP calls
|
|
106
95
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
"command": "npx",
|
|
112
|
-
"args": ["-y", "@atomicmail/mcp"],
|
|
113
|
-
"env": {
|
|
114
|
-
"ATOMIC_MAIL_AUTH_URL": "https://auth.atomicmail.io",
|
|
115
|
-
"ATOMIC_MAIL_API_URL": "https://api.atomicmail.io"
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
```
|
|
96
|
+
These files are created and rotated automatically by MCP tool calls. AgentSkill
|
|
97
|
+
CLI uses the same files.
|
|
98
|
+
|
|
99
|
+
## Defaults
|
|
121
100
|
|
|
122
|
-
|
|
101
|
+
- auth endpoint: `https://auth.atomicmail.ai`
|
|
102
|
+
- api endpoint: `https://api.atomicmail.ai`
|
|
103
|
+
- credentials directory: `~/.atomicmail`
|
|
123
104
|
|
|
124
|
-
|
|
125
|
-
repeated — the MCP reads URLs (and optional salt override) from `credentials.json`:
|
|
105
|
+
## Overriding defaults
|
|
126
106
|
|
|
127
107
|
```json
|
|
128
108
|
{
|
|
@@ -131,103 +111,13 @@ repeated — the MCP reads URLs (and optional salt override) from `credentials.j
|
|
|
131
111
|
"command": "npx",
|
|
132
112
|
"args": ["-y", "@atomicmail/mcp"],
|
|
133
113
|
"env": {
|
|
134
|
-
"
|
|
114
|
+
"ATOMIC_MAIL_AUTH_URL": "https://custom-auth.example",
|
|
115
|
+
"ATOMIC_MAIL_API_URL": "https://custom-api.example",
|
|
116
|
+
"ATOMIC_MAIL_CREDENTIALS_DIR": "/Users/me/.atomicmail",
|
|
117
|
+
"ATOMIC_MAIL_SCRYPT_SALT": "hex-salt-override",
|
|
118
|
+
"ATOMIC_MAIL_API_KEY": "existing-api-key"
|
|
135
119
|
}
|
|
136
120
|
}
|
|
137
121
|
}
|
|
138
122
|
}
|
|
139
123
|
```
|
|
140
|
-
|
|
141
|
-
When you skip the env entirely (`{}`), the MCP defaults to `~/.atomicmail/`.
|
|
142
|
-
|
|
143
|
-
## Typical agent workflow
|
|
144
|
-
|
|
145
|
-
Once the MCP is wired in, an agent will:
|
|
146
|
-
|
|
147
|
-
1. Call `register` (only on the first run, with no existing API key).
|
|
148
|
-
2. Call `jmap_session` to discover the `accountId` and the INBOX id.
|
|
149
|
-
3. Call `jmap_request` with whatever method calls it needs (inline) or reference
|
|
150
|
-
saved presets via `opsFile`.
|
|
151
|
-
4. Call `get_docs` with topic `presets` or `jmap_cheatsheet` for ready-to-use
|
|
152
|
-
JMAP recipes.
|
|
153
|
-
|
|
154
|
-
## JMAP presets (the `opsFile` parameter)
|
|
155
|
-
|
|
156
|
-
`jmap_request` accepts either an inline `methodCalls` array or an `opsFile`
|
|
157
|
-
path. Relative paths resolve against the credential directory, so common batches
|
|
158
|
-
can be saved once and reused. This mirrors the skill's
|
|
159
|
-
`atomic-mail-jmap --ops-file` behavior — both consume the same files.
|
|
160
|
-
|
|
161
|
-
Example: drop `~/.atomicmail/fetch_last_100.json` containing
|
|
162
|
-
|
|
163
|
-
```json
|
|
164
|
-
[
|
|
165
|
-
[
|
|
166
|
-
"Email/query",
|
|
167
|
-
{
|
|
168
|
-
"accountId": "ACC",
|
|
169
|
-
"filter": { "inMailbox": "INBOX" },
|
|
170
|
-
"sort": [{ "property": "receivedAt", "isAscending": false }],
|
|
171
|
-
"limit": 100
|
|
172
|
-
},
|
|
173
|
-
"q0"
|
|
174
|
-
]
|
|
175
|
-
]
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
…then `jmap_request` with `{ "opsFile": "fetch_last_100.json" }`.
|
|
179
|
-
|
|
180
|
-
See `get_docs presets` for the full preset format.
|
|
181
|
-
|
|
182
|
-
## Develop
|
|
183
|
-
|
|
184
|
-
The project is a Deno-first codebase. You'll need [Deno](https://deno.com/)
|
|
185
|
-
installed.
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
# Run directly with Deno (live source, no build step)
|
|
189
|
-
deno task start
|
|
190
|
-
|
|
191
|
-
# Type-check
|
|
192
|
-
deno task check
|
|
193
|
-
|
|
194
|
-
# Format
|
|
195
|
-
deno task fmt
|
|
196
|
-
|
|
197
|
-
# Build the npm package via dnt
|
|
198
|
-
deno task build:npm
|
|
199
|
-
|
|
200
|
-
# Run the built artifact under Node
|
|
201
|
-
node npm/esm/main.js
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
The dnt build emits to `./npm/`. The package's `bin` is `atomicmail-mcp`, mapped
|
|
205
|
-
to `npm/esm/main.js`. After a build you can also `npm install` it locally and
|
|
206
|
-
use the binary directly.
|
|
207
|
-
|
|
208
|
-
### Project layout
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
services/mcp-server-local/
|
|
212
|
-
├── deno.json # Deno config + import map
|
|
213
|
-
├── build_npm.ts # dnt build script
|
|
214
|
-
├── README.md
|
|
215
|
-
├── src/
|
|
216
|
-
│ ├── main.ts # MCP server entry (stdio transport)
|
|
217
|
-
│ ├── auth-session.ts# PoW + JWT rotation, with disk persistence
|
|
218
|
-
│ ├── credentials.ts # File I/O: credentials.json, *.jwt
|
|
219
|
-
│ ├── docs-content.ts# Static text served by the get_docs tool
|
|
220
|
-
│ └── tools/
|
|
221
|
-
│ ├── register.ts
|
|
222
|
-
│ ├── jmap.ts
|
|
223
|
-
│ └── docs.ts
|
|
224
|
-
└── npm/ # dnt output (gitignored)
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
The auth-session and credentials files are kept in-step with their counterparts
|
|
228
|
-
in [`skill/scripts/lib/`](../../skill/scripts/lib/) so both projects produce and
|
|
229
|
-
consume identical credential files.
|
|
230
|
-
|
|
231
|
-
## License
|
|
232
|
-
|
|
233
|
-
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,26 @@
|
|
|
1
|
+
export declare function fetchChallenge(authUrl: string): Promise<{
|
|
2
|
+
challengeJWT: string;
|
|
3
|
+
challenge: string;
|
|
4
|
+
difficulty: number;
|
|
5
|
+
}>;
|
|
6
|
+
export interface SessionResponse {
|
|
7
|
+
sessionJWT: string;
|
|
8
|
+
apiKey?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function exchangeSession(authUrl: string, body: {
|
|
11
|
+
challengeJWT: string;
|
|
12
|
+
powHex: string;
|
|
13
|
+
nonce: string;
|
|
14
|
+
apiKey?: string;
|
|
15
|
+
username?: string;
|
|
16
|
+
}): Promise<SessionResponse>;
|
|
17
|
+
export declare function fetchCapability(authUrl: string, sessionJWT: string): Promise<string>;
|
|
18
|
+
export interface PerformPoWInput {
|
|
19
|
+
authUrl: string;
|
|
20
|
+
scryptSalt: string;
|
|
21
|
+
apiKey?: string;
|
|
22
|
+
username?: string;
|
|
23
|
+
onPowProgress?: (nonce: bigint) => void;
|
|
24
|
+
}
|
|
25
|
+
export declare function performPoWAndSession(input: PerformPoWInput): Promise<SessionResponse>;
|
|
26
|
+
//# sourceMappingURL=agent-auth-http.d.ts.map
|
|
@@ -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,76 @@
|
|
|
1
|
+
// auth-service HTTP: challenge → session → capability.
|
|
2
|
+
import { decodeJwtPayload } from "./agent-jwt.js";
|
|
3
|
+
import { solvePow } from "./agent-pow.js";
|
|
4
|
+
async function postJson(url, body, headers = {}) {
|
|
5
|
+
const res = await fetch(url, {
|
|
6
|
+
method: "POST",
|
|
7
|
+
headers: {
|
|
8
|
+
...(body ? { "Content-Type": "application/json" } : {}),
|
|
9
|
+
...headers,
|
|
10
|
+
},
|
|
11
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
12
|
+
});
|
|
13
|
+
const text = await res.text();
|
|
14
|
+
const path = (() => {
|
|
15
|
+
try {
|
|
16
|
+
return new URL(url).pathname;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return url;
|
|
20
|
+
}
|
|
21
|
+
})();
|
|
22
|
+
if (!res.ok) {
|
|
23
|
+
throw new Error(`auth-service ${path} returned ${res.status}: ${text}`);
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(text);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
throw new Error(`auth-service ${path} returned non-JSON body: ${text}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function fetchChallenge(authUrl) {
|
|
33
|
+
const data = await postJson(`${authUrl}/api/v1/challenge`, undefined);
|
|
34
|
+
if (typeof data.challengeJWT !== "string") {
|
|
35
|
+
throw new Error("Challenge response missing challengeJWT.");
|
|
36
|
+
}
|
|
37
|
+
const payload = decodeJwtPayload(data.challengeJWT);
|
|
38
|
+
if (typeof payload.jti !== "string" ||
|
|
39
|
+
typeof payload.difficulty !== "number") {
|
|
40
|
+
throw new Error("Challenge JWT payload malformed (missing jti or difficulty).");
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
challengeJWT: data.challengeJWT,
|
|
44
|
+
challenge: payload.jti,
|
|
45
|
+
difficulty: payload.difficulty,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export async function exchangeSession(authUrl, body) {
|
|
49
|
+
const data = await postJson(`${authUrl}/api/v1/session`, { ...body });
|
|
50
|
+
if (typeof data.sessionJWT !== "string") {
|
|
51
|
+
throw new Error("Session response missing sessionJWT.");
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
sessionJWT: data.sessionJWT,
|
|
55
|
+
apiKey: typeof data.apiKey === "string" ? data.apiKey : undefined,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export async function fetchCapability(authUrl, sessionJWT) {
|
|
59
|
+
const data = await postJson(`${authUrl}/api/v1/capability`, undefined, { Authorization: `Bearer ${sessionJWT}` });
|
|
60
|
+
if (typeof data.capabilityJWT !== "string") {
|
|
61
|
+
throw new Error("Capability response missing capabilityJWT.");
|
|
62
|
+
}
|
|
63
|
+
return data.capabilityJWT;
|
|
64
|
+
}
|
|
65
|
+
export async function performPoWAndSession(input) {
|
|
66
|
+
const { authUrl, scryptSalt } = input;
|
|
67
|
+
const { challengeJWT, challenge, difficulty } = await fetchChallenge(authUrl);
|
|
68
|
+
const { powHex, nonce } = await solvePow(challenge, difficulty, scryptSalt, input.onPowProgress);
|
|
69
|
+
return exchangeSession(authUrl, {
|
|
70
|
+
challengeJWT,
|
|
71
|
+
powHex,
|
|
72
|
+
nonce,
|
|
73
|
+
apiKey: input.apiKey,
|
|
74
|
+
username: input.username,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const SESSION_TTL_MS: number;
|
|
2
|
+
export declare const CAPABILITY_TTL_MS: number;
|
|
3
|
+
export declare const SESSION_SAFETY_MARGIN_MS = 60000;
|
|
4
|
+
export declare const CAPABILITY_SAFETY_MARGIN_MS = 20000;
|
|
5
|
+
export interface JwtPayload {
|
|
6
|
+
exp?: number;
|
|
7
|
+
iat?: number;
|
|
8
|
+
jti?: string;
|
|
9
|
+
inboxId?: string;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
export declare function decodeJwtPayload<T = JwtPayload>(jwt: string): T;
|
|
13
|
+
export declare function isJwtExpired(jwt: string, marginMs: number): boolean;
|
|
14
|
+
//# sourceMappingURL=agent-jwt.d.ts.map
|
|
@@ -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"}
|