@atomicmail/agent-skill 0.1.0 → 0.2.0
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 +56 -0
- package/SKILL.md +67 -187
- package/esm/{skill/scripts/lib/auth.d.ts → lib/src/agent-auth-http.d.ts} +1 -17
- package/esm/lib/src/agent-auth-http.d.ts.map +1 -0
- package/esm/lib/src/agent-auth-http.js +76 -0
- package/esm/{skill/scripts/lib/credentials.d.ts → lib/src/agent-credentials-store.d.ts} +4 -1
- package/esm/lib/src/agent-credentials-store.d.ts.map +1 -0
- package/esm/{skill/scripts/lib/credentials.js → lib/src/agent-credentials-store.js} +28 -8
- package/esm/lib/src/agent-help-content.d.ts +4 -0
- package/esm/lib/src/agent-help-content.d.ts.map +1 -0
- package/esm/lib/src/agent-help-content.js +236 -0
- package/esm/lib/src/agent-jmap.d.ts +49 -0
- package/esm/lib/src/agent-jmap.d.ts.map +1 -0
- package/esm/lib/src/agent-jmap.js +130 -0
- package/esm/lib/src/agent-jwt.d.ts +14 -0
- package/esm/lib/src/agent-jwt.d.ts.map +1 -0
- package/esm/lib/src/agent-jwt.js +29 -0
- package/esm/lib/src/agent-pow.d.ts +5 -0
- package/esm/lib/src/agent-pow.d.ts.map +1 -0
- package/esm/lib/src/agent-pow.js +49 -0
- package/esm/lib/src/agent-session.d.ts +62 -0
- package/esm/lib/src/agent-session.d.ts.map +1 -0
- package/esm/lib/src/agent-session.js +206 -0
- package/esm/lib/src/agent-vars.d.ts +23 -0
- package/esm/lib/src/agent-vars.d.ts.map +1 -0
- package/esm/lib/src/agent-vars.js +65 -0
- package/esm/skill/scripts/cli.d.ts +3 -0
- package/esm/skill/scripts/cli.d.ts.map +1 -0
- package/esm/skill/scripts/cli.js +309 -0
- package/package.json +3 -4
- package/esm/skill/scripts/jmap_request.d.ts +0 -3
- package/esm/skill/scripts/jmap_request.d.ts.map +0 -1
- package/esm/skill/scripts/jmap_request.js +0 -265
- package/esm/skill/scripts/lib/auth.d.ts.map +0 -1
- package/esm/skill/scripts/lib/auth.js +0 -163
- package/esm/skill/scripts/lib/credentials.d.ts.map +0 -1
- package/esm/skill/scripts/signup.d.ts +0 -3
- package/esm/skill/scripts/signup.d.ts.map +0 -1
- package/esm/skill/scripts/signup.js +0 -170
package/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# @atomicmail/agent-skill
|
|
2
|
+
|
|
3
|
+
Atomic Mail AgentSkill CLI for AI agents. It exposes three commands: `register`,
|
|
4
|
+
`jmap_request`, and `help` (same surface as `@atomicmail/mcp`).
|
|
5
|
+
|
|
6
|
+
## Install / run
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx --package=@atomicmail/agent-skill atomicmail --help
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
From source:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
deno run -A scripts/cli.ts --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx --package=@atomicmail/agent-skill atomicmail register \
|
|
22
|
+
--username "myagent"
|
|
23
|
+
|
|
24
|
+
npx --package=@atomicmail/agent-skill atomicmail jmap_request \
|
|
25
|
+
--ops '[["Mailbox/get", {"accountId": "$ACCOUNT_ID"}, "m0"]]'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Placeholder substitution
|
|
29
|
+
|
|
30
|
+
- Built-in placeholders: `$ACCOUNT_ID`, `$INBOX`
|
|
31
|
+
- Custom placeholders: any `$VAR_NAME` via `--vars '{"VAR_NAME":"value"}'`
|
|
32
|
+
- Works for both `--ops` and `--ops-file`
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx --package=@atomicmail/agent-skill atomicmail jmap_request \
|
|
38
|
+
--ops-file send_email.json \
|
|
39
|
+
--vars '{"TO":"alice@example.com","SUBJECT":"Hello","BODY":"Hi there"}'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Shared state
|
|
43
|
+
|
|
44
|
+
Credential files in `~/.atomicmail` (mode `0600`):
|
|
45
|
+
|
|
46
|
+
- `credentials.json`
|
|
47
|
+
- `session.jwt`
|
|
48
|
+
- `capability.jwt`
|
|
49
|
+
|
|
50
|
+
The skill and MCP server share this layout.
|
|
51
|
+
|
|
52
|
+
## Overriding defaults
|
|
53
|
+
|
|
54
|
+
- Endpoints: `--auth-url`, `--api-url` or `ATOMIC_MAIL_AUTH_URL`, `ATOMIC_MAIL_API_URL`
|
|
55
|
+
- Credentials path: `--credentials-dir` or `ATOMIC_MAIL_CREDENTIALS_DIR`
|
|
56
|
+
- PoW salt: `--scrypt-salt` or `ATOMIC_MAIL_SCRYPT_SALT`
|
package/SKILL.md
CHANGED
|
@@ -1,242 +1,122 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
3
|
-
description: Read and write email through the Atomic Mail ESP from an AI agent. Handles
|
|
2
|
+
name: atomicmail
|
|
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
4
|
license: MIT
|
|
5
|
-
compatibility: Requires Deno 2.0+ to run scripts directly, or Node 20+ / Bun 1.1+ via `npx @
|
|
6
|
-
metadata:
|
|
7
|
-
author: atomic-mail
|
|
8
|
-
version: "0.1.0"
|
|
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.
|
|
9
6
|
---
|
|
10
7
|
|
|
11
8
|
# Atomic Mail
|
|
12
9
|
|
|
13
|
-
Atomic Mail
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
hides all of that behind two CLI scripts so the agent can focus on JMAP.
|
|
10
|
+
Atomic Mail exposes a programmable inbox over JMAP with PoW signup and JWT
|
|
11
|
+
rotation. This skill ships a single CLI entrypoint with three commands:
|
|
12
|
+
**`register`**, **`jmap_request`**, and **`help`** — matching the MCP server.
|
|
17
13
|
|
|
18
14
|
## When to use this skill
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
- Register a new inbox or log in with an existing API key.
|
|
17
|
+
- Send JMAP batches (inline JSON or preset files).
|
|
18
|
+
- Read built-in documentation (JMAP cheatsheet, presets, troubleshooting).
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
- Re-authenticate an existing Atomic Mail account using its API key.
|
|
24
|
-
- Read, search, or modify email via JMAP (`Mailbox/get`, `Email/query`,
|
|
25
|
-
`Email/get`, `Email/set`, etc.).
|
|
26
|
-
- Send email via JMAP (`EmailSubmission/set` with the
|
|
27
|
-
`urn:ietf:params:jmap:submission` capability).
|
|
28
|
-
- Discover the JMAP session object (`/.well-known/jmap`) to find the `accountId`
|
|
29
|
-
before issuing other JMAP method calls.
|
|
20
|
+
## Commands
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- **`scripts/signup.ts`** — One-time setup: performs PoW signup or login and
|
|
34
|
-
writes credentials to disk. Run once per agent session/inbox.
|
|
35
|
-
- **`scripts/jmap_request.ts`** — Sends JMAP requests using the saved
|
|
36
|
-
credentials. Auto-rotates the session and capability JWTs as they expire.
|
|
37
|
-
|
|
38
|
-
Both scripts are invokable three ways. Pick the one that matches the runtime the
|
|
39
|
-
user has installed:
|
|
22
|
+
All invocations use `scripts/cli.ts` or the published binary **`atomicmail`**:
|
|
40
23
|
|
|
41
24
|
```bash
|
|
42
|
-
# Deno (
|
|
43
|
-
deno run -A scripts/
|
|
44
|
-
deno run -A scripts/
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
npx
|
|
49
|
-
|
|
50
|
-
# Bun
|
|
51
|
-
bunx -y @atomic-mail/agent-skill atomic-mail-signup ...
|
|
52
|
-
bunx -y @atomic-mail/agent-skill atomic-mail-jmap ...
|
|
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
|
|
53
33
|
```
|
|
54
34
|
|
|
55
|
-
|
|
56
|
-
> spelling. Both scripts print full usage to stdout and exit `0`.
|
|
57
|
-
|
|
58
|
-
## Required configuration
|
|
35
|
+
Run **`atomicmail --help`** or **`atomicmail <command> --help`** for flags.
|
|
59
36
|
|
|
60
|
-
|
|
61
|
-
flags or set them in the environment:
|
|
37
|
+
## Defaults
|
|
62
38
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
| `--api-url` | `ATOMIC_MAIL_API_URL` | Base URL of `api-service` (JMAP). |
|
|
67
|
-
| `--scrypt-salt` | `ATOMIC_MAIL_SCRYPT_SALT` | Optional PoW salt override (defaults match `auth-service`). |
|
|
68
|
-
|
|
69
|
-
If the user does not know the URLs, ask them — they are deployment-specific.
|
|
39
|
+
- `authUrl`: `https://auth.atomicmail.ai`
|
|
40
|
+
- `apiUrl`: `https://api.atomicmail.ai`
|
|
41
|
+
- credentials directory: `~/.atomicmail`
|
|
70
42
|
|
|
71
43
|
## Workflow
|
|
72
44
|
|
|
73
|
-
### 1.
|
|
45
|
+
### 1. Register (new account)
|
|
74
46
|
|
|
75
47
|
```bash
|
|
76
|
-
deno run -A scripts/
|
|
77
|
-
--
|
|
78
|
-
--api-url "$ATOMIC_MAIL_API_URL" \
|
|
79
|
-
--username "alice" \
|
|
80
|
-
--out-dir "./.atomic-mail"
|
|
48
|
+
deno run -A scripts/cli.ts register \
|
|
49
|
+
--username "alice"
|
|
81
50
|
```
|
|
82
51
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
- `credentials.json` — `{ apiKey, inboxId, authUrl, apiUrl, scryptSalt }`. The
|
|
86
|
-
agent should store the `apiKey` securely; it is the long-lived secret.
|
|
87
|
-
- `session.jwt` — 4-hour session token.
|
|
88
|
-
- `capability.jwt` — 2-minute capability token used as the JMAP bearer.
|
|
52
|
+
Writes `credentials.json`, `session.jwt`, `capability.jwt`. Prints JSON
|
|
53
|
+
including `inbox` and `accountId`.
|
|
89
54
|
|
|
90
|
-
|
|
91
|
-
Save these in the agent's persistent memory (or echo them back to the user) —
|
|
92
|
-
they are the only durable identifiers.
|
|
55
|
+
### 2. Register (existing API key, in case losing the credentials file)
|
|
93
56
|
|
|
94
|
-
|
|
57
|
+
```bash
|
|
58
|
+
deno run -A scripts/cli.ts register \
|
|
59
|
+
--api-key "..."
|
|
60
|
+
```
|
|
95
61
|
|
|
96
|
-
|
|
97
|
-
`jmap_request.ts` will auto-renew session/capability tokens via the stored API
|
|
98
|
-
key. Use `signup.ts --api-key` only if the user wants to start a fresh
|
|
99
|
-
credentials directory from a known API key.
|
|
62
|
+
### 3. JMAP request
|
|
100
63
|
|
|
101
64
|
```bash
|
|
102
|
-
deno run -A scripts/
|
|
103
|
-
--
|
|
104
|
-
--api-url "$ATOMIC_MAIL_API_URL" \
|
|
105
|
-
--api-key "11111111-2222-3333-4444-555555555555" \
|
|
106
|
-
--out-dir "./.atomic-mail"
|
|
65
|
+
deno run -A scripts/cli.ts jmap_request \
|
|
66
|
+
--ops '[["Mailbox/get", {"accountId": "$ACCOUNT_ID"}, "m0"]]'
|
|
107
67
|
```
|
|
108
68
|
|
|
109
|
-
|
|
69
|
+
`$ACCOUNT_ID` and `$INBOX` resolve from the session/credentials. Other
|
|
70
|
+
placeholders such as `$TO` or `$SUBJECT` require `--vars` with a JSON object of
|
|
71
|
+
strings (same substitution applies to `--ops` and `--ops-file`).
|
|
110
72
|
|
|
111
|
-
|
|
112
|
-
mailbox structure.
|
|
73
|
+
Preset file:
|
|
113
74
|
|
|
114
75
|
```bash
|
|
115
|
-
deno run -A scripts/
|
|
116
|
-
--
|
|
117
|
-
--session
|
|
76
|
+
deno run -A scripts/cli.ts jmap_request \
|
|
77
|
+
--ops-file fetch_last_100.json
|
|
118
78
|
```
|
|
119
79
|
|
|
120
|
-
|
|
121
|
-
Extract the `accountId` for the user's primary mail account from
|
|
122
|
-
`primaryAccounts["urn:ietf:params:jmap:mail"]`.
|
|
123
|
-
|
|
124
|
-
### 4. Send a JMAP request (inline ops)
|
|
80
|
+
With custom placeholders:
|
|
125
81
|
|
|
126
82
|
```bash
|
|
127
|
-
deno run -A scripts/
|
|
128
|
-
--
|
|
129
|
-
--
|
|
83
|
+
deno run -A scripts/cli.ts jmap_request \
|
|
84
|
+
--ops-file send_email.json \
|
|
85
|
+
--vars '{"TO":"alice@example.com","SUBJECT":"Hello","BODY":"Hi there"}'
|
|
130
86
|
```
|
|
131
87
|
|
|
132
|
-
|
|
88
|
+
### 4. Help
|
|
133
89
|
|
|
134
90
|
```bash
|
|
135
|
-
deno run -A scripts/
|
|
136
|
-
|
|
137
|
-
--ops '{
|
|
138
|
-
"using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"],
|
|
139
|
-
"methodCalls": [
|
|
140
|
-
["Mailbox/get", {"accountId": "ACCOUNT_ID"}, "m0"],
|
|
141
|
-
["Email/query", {"accountId": "ACCOUNT_ID", "limit": 10}, "q0"]
|
|
142
|
-
]
|
|
143
|
-
}'
|
|
91
|
+
deno run -A scripts/cli.ts help
|
|
92
|
+
deno run -A scripts/cli.ts help --topic jmap_cheatsheet
|
|
144
93
|
```
|
|
145
94
|
|
|
146
|
-
|
|
95
|
+
## npm package
|
|
147
96
|
|
|
148
|
-
|
|
149
|
-
contain either a `methodCalls` array or a full `{ using, methodCalls }`
|
|
150
|
-
envelope.
|
|
97
|
+
From the `skill/` directory:
|
|
151
98
|
|
|
152
99
|
```bash
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
["Email/query", {
|
|
156
|
-
"accountId": "ACCOUNT_ID",
|
|
157
|
-
"limit": 100,
|
|
158
|
-
"sort": [{ "property": "receivedAt", "isAscending": false }]
|
|
159
|
-
}, "q0"],
|
|
160
|
-
["Email/get", {
|
|
161
|
-
"accountId": "ACCOUNT_ID",
|
|
162
|
-
"#ids": { "resultOf": "q0", "name": "Email/query", "path": "/ids" },
|
|
163
|
-
"properties": ["id","threadId","subject","from","receivedAt","preview"]
|
|
164
|
-
}, "g0"]
|
|
165
|
-
]
|
|
166
|
-
EOF
|
|
167
|
-
|
|
168
|
-
deno run -A scripts/jmap_request.ts \
|
|
169
|
-
--credentials-dir "./.atomic-mail" \
|
|
170
|
-
--ops-file fetch_last_100.json
|
|
100
|
+
deno task build:npm
|
|
101
|
+
cd npm && npm publish --access public
|
|
171
102
|
```
|
|
172
103
|
|
|
173
|
-
The
|
|
174
|
-
`
|
|
104
|
+
The published **`atomicmail`** binary exposes `register`, `jmap_request`, and
|
|
105
|
+
`help`.
|
|
175
106
|
|
|
176
|
-
|
|
107
|
+
## Security
|
|
177
108
|
|
|
178
|
-
|
|
179
|
-
|
|
109
|
+
- `credentials.json` holds the API key (mode `0600`). Do not commit it.
|
|
110
|
+
- JWT files are bearer secrets — do not log them.
|
|
180
111
|
|
|
181
|
-
|
|
182
|
-
deno run -A scripts/jmap_request.ts \
|
|
183
|
-
--credentials-dir "./.atomic-mail" \
|
|
184
|
-
--using "urn:ietf:params:jmap:core,urn:ietf:params:jmap:mail,urn:ietf:params:jmap:submission" \
|
|
185
|
-
--ops-file send_email.json
|
|
186
|
-
```
|
|
112
|
+
## Overriding defaults
|
|
187
113
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
- If `capability.jwt` is within 20 s of expiry, it calls
|
|
193
|
-
`POST /api/v1/capability` with the existing session JWT and rewrites
|
|
194
|
-
`capability.jwt`.
|
|
195
|
-
- If `session.jwt` is within 60 s of expiry (or missing), it re-runs the full
|
|
196
|
-
PoW handshake using the API key from `credentials.json`, then rewrites both
|
|
197
|
-
`session.jwt` and `capability.jwt`.
|
|
198
|
-
|
|
199
|
-
The agent does not need to call `signup.ts` again to refresh tokens — it only
|
|
200
|
-
needs to call `signup.ts` for the very first registration of an account.
|
|
201
|
-
|
|
202
|
-
## Troubleshooting
|
|
203
|
-
|
|
204
|
-
- **`Could not read credentials file ... Did you run signup first?`** — Run
|
|
205
|
-
`signup.ts` once with `--username` (new account) or `--api-key` (existing
|
|
206
|
-
account) to create the file set.
|
|
207
|
-
- **`auth-service /api/v1/session returned 409`** — The challenge was consumed
|
|
208
|
-
(likely a duplicate request or a clock skew). Just rerun `signup.ts` or the
|
|
209
|
-
failing `jmap_request.ts` once; a fresh challenge will be issued.
|
|
210
|
-
- **`auth-service /api/v1/session returned 401`** — The `apiKey` in
|
|
211
|
-
`credentials.json` is unknown or suspended. Re-register with `--username` or
|
|
212
|
-
get a new API key from the operator.
|
|
213
|
-
- **PoW takes a long time on first run** — Difficulty is fixed at 6 leading zero
|
|
214
|
-
bits, which averages ~64 scrypt iterations. Each scrypt is ~16 MB and ~200-500
|
|
215
|
-
ms, so the whole solve typically completes in under 30 seconds on a modern
|
|
216
|
-
laptop.
|
|
217
|
-
- **`Capability JWT did not contain an inboxId claim`** — Almost certainly a
|
|
218
|
-
server/version mismatch. Verify `--auth-url` points to a current
|
|
219
|
-
`auth-service` deployment.
|
|
220
|
-
|
|
221
|
-
## Security notes
|
|
222
|
-
|
|
223
|
-
- `credentials.json` contains the long-lived API key. The script writes it with
|
|
224
|
-
mode `0600`, but the agent must not echo the file's contents into shared logs
|
|
225
|
-
or commit it to source control.
|
|
226
|
-
- Pick a credentials directory that is private to the agent's runtime user (e.g.
|
|
227
|
-
`~/.config/atomic-mail/` or a per-task working dir).
|
|
228
|
-
- `session.jwt` and `capability.jwt` are short-lived but should be treated as
|
|
229
|
-
bearer credentials too — never log them.
|
|
230
|
-
|
|
231
|
-
## Building an npm package
|
|
232
|
-
|
|
233
|
-
Scripts can be published as an npm package so Node and Bun environments can use
|
|
234
|
-
them through `npx` / `bunx`. From the skill directory:
|
|
114
|
+
- Endpoints: `--auth-url`, `--api-url` or `ATOMIC_MAIL_AUTH_URL`,
|
|
115
|
+
`ATOMIC_MAIL_API_URL`
|
|
116
|
+
- Credentials path: `--credentials-dir` or `ATOMIC_MAIL_CREDENTIALS_DIR`
|
|
117
|
+
- PoW salt: `--scrypt-salt` or `ATOMIC_MAIL_SCRYPT_SALT`
|
|
235
118
|
|
|
236
|
-
|
|
237
|
-
deno task build:npm # writes ./npm
|
|
238
|
-
cd npm && npm publish --access public
|
|
239
|
-
```
|
|
119
|
+
## Building
|
|
240
120
|
|
|
241
|
-
|
|
242
|
-
|
|
121
|
+
See repository [`AGENTS.md`](../AGENTS.md) for formatting (`deno fmt`) and
|
|
122
|
+
conventions.
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
export declare const SESSION_TTL_MS: number;
|
|
2
|
-
export declare const CAPABILITY_TTL_MS: number;
|
|
3
|
-
export declare const CAPABILITY_SAFETY_MARGIN_MS = 20000;
|
|
4
|
-
export declare const SESSION_SAFETY_MARGIN_MS = 60000;
|
|
5
|
-
export interface JwtPayload {
|
|
6
|
-
exp?: number;
|
|
7
|
-
iat?: number;
|
|
8
|
-
jti?: string;
|
|
9
|
-
[key: string]: unknown;
|
|
10
|
-
}
|
|
11
|
-
export declare function decodeJwtPayload<T = JwtPayload>(jwt: string): T;
|
|
12
|
-
export declare function isJwtExpired(jwt: string, marginMs: number): boolean;
|
|
13
|
-
export declare function solvePow(challenge: string, difficulty: number, salt: string, onProgress?: (nonce: bigint) => void): Promise<{
|
|
14
|
-
powHex: string;
|
|
15
|
-
nonce: string;
|
|
16
|
-
}>;
|
|
17
1
|
export declare function fetchChallenge(authUrl: string): Promise<{
|
|
18
2
|
challengeJWT: string;
|
|
19
3
|
challenge: string;
|
|
@@ -39,4 +23,4 @@ export interface PerformPoWInput {
|
|
|
39
23
|
onPowProgress?: (nonce: bigint) => void;
|
|
40
24
|
}
|
|
41
25
|
export declare function performPoWAndSession(input: PerformPoWInput): Promise<SessionResponse>;
|
|
42
|
-
//# sourceMappingURL=auth.d.ts.map
|
|
26
|
+
//# sourceMappingURL=agent-auth-http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-auth-http.d.ts","sourceRoot":"","sources":["../../../src/lib/src/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
|
+
}
|
|
@@ -13,6 +13,9 @@ export interface SkillFiles {
|
|
|
13
13
|
export declare function defaultFilesFromOutDir(outDir: string): SkillFiles;
|
|
14
14
|
export declare function writeCredentials(path: string, creds: Credentials): Promise<void>;
|
|
15
15
|
export declare function readCredentials(path: string): Promise<Credentials>;
|
|
16
|
+
export declare function tryReadCredentials(path: string): Promise<Credentials | undefined>;
|
|
16
17
|
export declare function writeJwtFile(path: string, jwt: string): Promise<void>;
|
|
17
18
|
export declare function tryReadJwtFile(path: string): Promise<string | undefined>;
|
|
18
|
-
|
|
19
|
+
/** Best-effort removal of credential artifacts (ignore missing files). */
|
|
20
|
+
export declare function unlinkCredentialArtifacts(files: SkillFiles): Promise<void>;
|
|
21
|
+
//# sourceMappingURL=agent-credentials-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-credentials-store.d.ts","sourceRoot":"","sources":["../../../src/lib/src/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"}
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
// Credential file I/O
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
// capability.jwt — short-lived (~2min): rotates via /capability.
|
|
5
|
-
//
|
|
6
|
-
// Files are written with mode 0600 so other local users cannot read them.
|
|
7
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
// Credential file I/O shared by MCP and AgentSkill.
|
|
2
|
+
// Three files: credentials.json, session.jwt, capability.jwt (mode 0600).
|
|
3
|
+
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
8
4
|
import { dirname, join, resolve } from "node:path";
|
|
9
5
|
export function defaultFilesFromOutDir(outDir) {
|
|
10
6
|
const base = resolve(outDir);
|
|
@@ -28,7 +24,7 @@ export async function readCredentials(path) {
|
|
|
28
24
|
}
|
|
29
25
|
catch (err) {
|
|
30
26
|
throw new Error(`Could not read credentials file '${path}': ${err.message}. ` +
|
|
31
|
-
"Did you run
|
|
27
|
+
"Did you run register first?");
|
|
32
28
|
}
|
|
33
29
|
let obj;
|
|
34
30
|
try {
|
|
@@ -51,6 +47,15 @@ export async function readCredentials(path) {
|
|
|
51
47
|
}
|
|
52
48
|
return obj;
|
|
53
49
|
}
|
|
50
|
+
export async function tryReadCredentials(path) {
|
|
51
|
+
try {
|
|
52
|
+
await readFile(path, "utf-8");
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return readCredentials(path);
|
|
58
|
+
}
|
|
54
59
|
export async function writeJwtFile(path, jwt) {
|
|
55
60
|
await ensureParent(path);
|
|
56
61
|
await writeFile(path, jwt, { mode: 0o600 });
|
|
@@ -64,3 +69,18 @@ export async function tryReadJwtFile(path) {
|
|
|
64
69
|
return undefined;
|
|
65
70
|
}
|
|
66
71
|
}
|
|
72
|
+
/** Best-effort removal of credential artifacts (ignore missing files). */
|
|
73
|
+
export async function unlinkCredentialArtifacts(files) {
|
|
74
|
+
for (const p of [
|
|
75
|
+
files.credentialsFile,
|
|
76
|
+
files.sessionFile,
|
|
77
|
+
files.capabilityFile,
|
|
78
|
+
]) {
|
|
79
|
+
try {
|
|
80
|
+
await unlink(p);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// ignore
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-help-content.d.ts","sourceRoot":"","sources":["../../../src/lib/src/agent-help-content.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAuO9C,CAAC;AAEF,eAAO,MAAM,eAAe,UAA2B,CAAC;AAExD,wBAAgB,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAW9C"}
|