aamp-openclaw-plugin 0.1.27 → 0.1.29
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 +14 -0
- package/bin/aamp-openclaw-plugin.mjs +52 -27
- package/dist/file-store.js +37 -3
- package/dist/file-store.js.map +2 -2
- package/dist/index.js +695 -91
- package/dist/index.js.map +3 -3
- package/package.json +5 -3
- package/skills/SKILL.md +36 -32
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"skills"
|
|
8
8
|
],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.1.
|
|
10
|
+
"version": "0.1.29",
|
|
11
11
|
"description": "AAMP Agent Mail Protocol — OpenClaw plugin. Gives OpenClaw an AAMP mailbox identity and lets it receive, process and reply to AAMP tasks.",
|
|
12
12
|
"type": "module",
|
|
13
13
|
"main": "dist/index.js",
|
|
@@ -65,7 +65,8 @@
|
|
|
65
65
|
"build": "node esbuild.config.js",
|
|
66
66
|
"dev": "node esbuild.config.js --watch",
|
|
67
67
|
"prepare": "npm run build",
|
|
68
|
-
"prepack": "npm run build"
|
|
68
|
+
"prepack": "npm run build",
|
|
69
|
+
"test": "vitest run"
|
|
69
70
|
},
|
|
70
71
|
"dependencies": {
|
|
71
72
|
"nodemailer": "^6.9.10",
|
|
@@ -74,6 +75,7 @@
|
|
|
74
75
|
"devDependencies": {
|
|
75
76
|
"@types/node": "^20.11.30",
|
|
76
77
|
"esbuild": "^0.20.2",
|
|
77
|
-
"typescript": "^5.4.3"
|
|
78
|
+
"typescript": "^5.4.3",
|
|
79
|
+
"vitest": "^1.6.1"
|
|
78
80
|
}
|
|
79
81
|
}
|
package/skills/SKILL.md
CHANGED
|
@@ -46,12 +46,13 @@ needed.
|
|
|
46
46
|
|
|
47
47
|
| Endpoint | Auth | Purpose |
|
|
48
48
|
|---|---|---|
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `GET /api/
|
|
52
|
-
| `
|
|
49
|
+
| `GET /.well-known/aamp` | None | Discover the canonical AAMP API entrypoint |
|
|
50
|
+
| `POST /api/aamp?action=aamp.mailbox.register` | None | Create a new agent mailbox (returns one-time code) |
|
|
51
|
+
| `GET /api/aamp?action=aamp.mailbox.credentials&code=XXX` | None | Exchange one-time code for credentials |
|
|
52
|
+
| `GET /api/aamp?action=aamp.mailbox.inbox` | Basic `mailboxToken` | List pending tasks for this agent |
|
|
53
|
+
| `POST /api/aamp?action=aamp.mailbox.send` | Basic `mailboxToken` | Send an email (with optional AAMP headers) |
|
|
53
54
|
|
|
54
|
-
**`
|
|
55
|
+
**`mailboxToken`** = `base64(email:smtpPassword)` — the same credential is used
|
|
55
56
|
for both the REST endpoints above and for JMAP WebSocket Push (`/jmap/*`).
|
|
56
57
|
|
|
57
58
|
---
|
|
@@ -65,7 +66,13 @@ exchange the code for credentials.
|
|
|
65
66
|
### Step 1a — Self-register
|
|
66
67
|
|
|
67
68
|
```
|
|
68
|
-
|
|
69
|
+
GET {AAMP_HOST}/.well-known/aamp
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The discovery document returns the canonical AAMP API entrypoint (for example `/api/aamp`).
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
POST {AAMP_HOST}{AAMP_API_URL}?action=aamp.mailbox.register
|
|
69
76
|
Content-Type: application/json
|
|
70
77
|
|
|
71
78
|
{ "slug": "{AAMP_SLUG}", "description": "OpenClaw AAMP agent" }
|
|
@@ -79,7 +86,7 @@ Content-Type: application/json
|
|
|
79
86
|
"description": "OpenClaw AAMP agent",
|
|
80
87
|
"registrationCode": "<64-char hex code>",
|
|
81
88
|
"expiresInSeconds": 300,
|
|
82
|
-
"
|
|
89
|
+
"credentialsAction": "aamp.mailbox.credentials"
|
|
83
90
|
}
|
|
84
91
|
```
|
|
85
92
|
|
|
@@ -89,14 +96,14 @@ The response does NOT include credentials. Instead it returns a one-time
|
|
|
89
96
|
### Step 1b — Exchange code for credentials
|
|
90
97
|
|
|
91
98
|
```
|
|
92
|
-
GET {AAMP_HOST}
|
|
99
|
+
GET {AAMP_HOST}{AAMP_API_URL}?action=aamp.mailbox.credentials&code={registrationCode}
|
|
93
100
|
```
|
|
94
101
|
|
|
95
102
|
**Response (200):**
|
|
96
103
|
```json
|
|
97
104
|
{
|
|
98
105
|
"email": "openclaw-agent-a1b2c3d4@aamp.local",
|
|
99
|
-
"
|
|
106
|
+
"mailbox": { "token": "<base64 mailboxToken>" },
|
|
100
107
|
"smtp": { "password": "<smtpPassword>" }
|
|
101
108
|
}
|
|
102
109
|
```
|
|
@@ -112,7 +119,7 @@ mailboxes without conflict (e.g. `openclaw-agent-a1b2c3d4`,
|
|
|
112
119
|
|
|
113
120
|
**Important — credential lifecycle:**
|
|
114
121
|
|
|
115
|
-
1. After exchanging the code, immediately save `email`, `
|
|
122
|
+
1. After exchanging the code, immediately save `email`, `mailbox.token`, and
|
|
116
123
|
`smtp.password` to `AAMP_CREDENTIALS_FILE`.
|
|
117
124
|
2. At startup: load the credentials file first. **Only call self-register if
|
|
118
125
|
the file is absent or incomplete** (missing any of the three fields) —
|
|
@@ -127,8 +134,8 @@ mailboxes without conflict (e.g. `openclaw-agent-a1b2c3d4`,
|
|
|
127
134
|
Poll for tasks dispatched to this agent that are waiting for a response.
|
|
128
135
|
|
|
129
136
|
```
|
|
130
|
-
GET {AAMP_HOST}
|
|
131
|
-
Authorization: Basic {
|
|
137
|
+
GET {AAMP_HOST}{AAMP_API_URL}?action=aamp.mailbox.inbox
|
|
138
|
+
Authorization: Basic {mailboxToken}
|
|
132
139
|
```
|
|
133
140
|
|
|
134
141
|
**Success response:**
|
|
@@ -139,8 +146,7 @@ Authorization: Basic {jmapToken}
|
|
|
139
146
|
"fromAgent": "meego-abc123@aamp.local",
|
|
140
147
|
"title": "Review PR #42",
|
|
141
148
|
"contextLinks": ["https://github.com/org/repo/pull/42"],
|
|
142
|
-
"
|
|
143
|
-
"timeoutAt": "2026-03-17T09:00:00.000Z",
|
|
149
|
+
"expiresAt": "2026-03-17T09:00:00.000Z",
|
|
144
150
|
"dispatchedAt": "2026-03-17T08:00:00.000Z",
|
|
145
151
|
"createdAt": "2026-03-17T08:00:00.000Z"
|
|
146
152
|
}
|
|
@@ -156,8 +162,8 @@ An empty array means no pending tasks.
|
|
|
156
162
|
After completing a task, reply to the dispatcher with a `task.result` email.
|
|
157
163
|
|
|
158
164
|
```
|
|
159
|
-
POST {AAMP_HOST}
|
|
160
|
-
Authorization: Basic {
|
|
165
|
+
POST {AAMP_HOST}{AAMP_API_URL}?action=aamp.mailbox.send
|
|
166
|
+
Authorization: Basic {mailboxToken}
|
|
161
167
|
Content-Type: application/json
|
|
162
168
|
|
|
163
169
|
{
|
|
@@ -167,24 +173,23 @@ Content-Type: application/json
|
|
|
167
173
|
"aampHeaders": {
|
|
168
174
|
"X-AAMP-Intent": "task.result",
|
|
169
175
|
"X-AAMP-TaskId": "<taskId>",
|
|
170
|
-
"X-AAMP-Status": "completed"
|
|
171
|
-
"X-AAMP-Output": "<structured result, JSON-encoded string or plain text>"
|
|
176
|
+
"X-AAMP-Status": "completed"
|
|
172
177
|
}
|
|
173
178
|
}
|
|
174
179
|
```
|
|
175
180
|
|
|
176
|
-
|
|
177
|
-
`
|
|
181
|
+
Put the human-readable output or rejection reason in the email body. Keep
|
|
182
|
+
`X-AAMP-StructuredResult` only when you need structured writeback fields.
|
|
178
183
|
|
|
179
184
|
---
|
|
180
185
|
|
|
181
186
|
## Step 3b — Send Help Request
|
|
182
187
|
|
|
183
|
-
If the agent is blocked and needs human input, send a `task.
|
|
188
|
+
If the agent is blocked and needs human input, send a `task.help_needed` email instead.
|
|
184
189
|
|
|
185
190
|
```
|
|
186
|
-
POST {AAMP_HOST}
|
|
187
|
-
Authorization: Basic {
|
|
191
|
+
POST {AAMP_HOST}{AAMP_API_URL}?action=aamp.mailbox.send
|
|
192
|
+
Authorization: Basic {mailboxToken}
|
|
188
193
|
Content-Type: application/json
|
|
189
194
|
|
|
190
195
|
{
|
|
@@ -192,17 +197,16 @@ Content-Type: application/json
|
|
|
192
197
|
"subject": "[AAMP Help] {title}",
|
|
193
198
|
"text": "<human-readable description of the blocker>",
|
|
194
199
|
"aampHeaders": {
|
|
195
|
-
"X-AAMP-Intent": "task.
|
|
200
|
+
"X-AAMP-Intent": "task.help_needed",
|
|
196
201
|
"X-AAMP-TaskId": "<taskId>",
|
|
197
|
-
"X-AAMP-Question": "<specific question for the human>",
|
|
198
|
-
"X-AAMP-BlockedReason": "<why the agent is stuck>",
|
|
199
202
|
"X-AAMP-SuggestedOptions": "<option A|option B|option C>"
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
```
|
|
203
206
|
|
|
204
|
-
`X-AAMP-SuggestedOptions`
|
|
205
|
-
|
|
207
|
+
Put the question and blocked reason in the email body. `X-AAMP-SuggestedOptions`
|
|
208
|
+
remains pipe-separated; include 2–4 options when possible to make it easy for
|
|
209
|
+
the human to respond quickly.
|
|
206
210
|
|
|
207
211
|
---
|
|
208
212
|
|
|
@@ -210,18 +214,18 @@ to make it easy for the human to respond quickly.
|
|
|
210
214
|
|
|
211
215
|
- **401** on any endpoint → credentials invalid. Delete the credentials file
|
|
212
216
|
and call self-register again to get a fresh mailbox.
|
|
213
|
-
- **502** on
|
|
214
|
-
- **500** on
|
|
217
|
+
- **502** on `aamp.mailbox.send` → SMTP delivery failed. Retry after a short delay.
|
|
218
|
+
- **500** on `aamp.mailbox.register` → management service unavailable.
|
|
215
219
|
Retry with exponential back-off.
|
|
216
220
|
|
|
217
221
|
---
|
|
218
222
|
|
|
219
223
|
## JMAP WebSocket Push (optional, real-time)
|
|
220
224
|
|
|
221
|
-
For real-time task delivery instead of polling
|
|
225
|
+
For real-time task delivery instead of polling `aamp.mailbox.inbox`, connect a WebSocket
|
|
222
226
|
to `{AAMP_HOST}/jmap` and subscribe to the `EmailDelivery` push channel.
|
|
223
227
|
The management service proxies this connection to the Stalwart mail server.
|
|
224
228
|
|
|
225
|
-
Use `Authorization: Basic {
|
|
229
|
+
Use `Authorization: Basic {mailboxToken}` when upgrading the WebSocket connection.
|
|
226
230
|
Parse incoming `Email/get` changes and filter for messages with `X-AAMP-Intent`
|
|
227
231
|
header to detect task dispatches without polling.
|