agentdial 1.0.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/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.md +310 -0
- package/dist/adapters/discord.d.ts +24 -0
- package/dist/adapters/discord.d.ts.map +1 -0
- package/dist/adapters/discord.js +129 -0
- package/dist/adapters/discord.js.map +1 -0
- package/dist/adapters/email.d.ts +38 -0
- package/dist/adapters/email.d.ts.map +1 -0
- package/dist/adapters/email.js +187 -0
- package/dist/adapters/email.js.map +1 -0
- package/dist/adapters/index.d.ts +12 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +36 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/slack.d.ts +27 -0
- package/dist/adapters/slack.d.ts.map +1 -0
- package/dist/adapters/slack.js +173 -0
- package/dist/adapters/slack.js.map +1 -0
- package/dist/adapters/telegram.d.ts +28 -0
- package/dist/adapters/telegram.d.ts.map +1 -0
- package/dist/adapters/telegram.js +155 -0
- package/dist/adapters/telegram.js.map +1 -0
- package/dist/adapters/twilio-sms.d.ts +36 -0
- package/dist/adapters/twilio-sms.d.ts.map +1 -0
- package/dist/adapters/twilio-sms.js +187 -0
- package/dist/adapters/twilio-sms.js.map +1 -0
- package/dist/adapters/twilio-whatsapp.d.ts +37 -0
- package/dist/adapters/twilio-whatsapp.d.ts.map +1 -0
- package/dist/adapters/twilio-whatsapp.js +188 -0
- package/dist/adapters/twilio-whatsapp.js.map +1 -0
- package/dist/adapters/types.d.ts +349 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +82 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/voice.d.ts +54 -0
- package/dist/adapters/voice.d.ts.map +1 -0
- package/dist/adapters/voice.js +250 -0
- package/dist/adapters/voice.js.map +1 -0
- package/dist/commands/channels.d.ts +5 -0
- package/dist/commands/channels.d.ts.map +1 -0
- package/dist/commands/channels.js +188 -0
- package/dist/commands/channels.js.map +1 -0
- package/dist/commands/mcp-serve.d.ts +14 -0
- package/dist/commands/mcp-serve.d.ts.map +1 -0
- package/dist/commands/mcp-serve.js +479 -0
- package/dist/commands/mcp-serve.js.map +1 -0
- package/dist/commands/serve.d.ts +6 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +128 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/setup.d.ts +4 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +174 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/status.d.ts +4 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +86 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/test.d.ts +5 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +48 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/voice.d.ts +6 -0
- package/dist/commands/voice.d.ts.map +1 -0
- package/dist/commands/voice.js +192 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +36 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +13 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +52 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/credentials.d.ts +7 -0
- package/dist/lib/credentials.d.ts.map +1 -0
- package/dist/lib/credentials.js +61 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/gateway.d.ts +27 -0
- package/dist/lib/gateway.d.ts.map +1 -0
- package/dist/lib/gateway.js +103 -0
- package/dist/lib/gateway.js.map +1 -0
- package/dist/lib/identity.d.ts +5 -0
- package/dist/lib/identity.d.ts.map +1 -0
- package/dist/lib/identity.js +36 -0
- package/dist/lib/identity.js.map +1 -0
- package/dist/lib/ui.d.ts +12 -0
- package/dist/lib/ui.d.ts.map +1 -0
- package/dist/lib/ui.js +91 -0
- package/dist/lib/ui.js.map +1 -0
- package/package.json +95 -0
- package/templates/IDENTITY.md +59 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0 (2026-03-28)
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **Agent Identity Protocol (AIP) v1.0** -- single `IDENTITY.md` file defines agent name, personality, channels, and backend URL with YAML frontmatter
|
|
10
|
+
- **10 channel adapters** -- Telegram, Discord, Slack, SMS, WhatsApp, Email, Voice, Teams, Messenger, Web Widget
|
|
11
|
+
- **Unified gateway** -- normalizes all incoming messages to `GatewayMessage` format and routes to any HTTP agent backend
|
|
12
|
+
- **Per-channel response formatting** -- Markdown for Telegram, embeds for Discord, blocks for Slack, plain text fallback
|
|
13
|
+
- **Interactive setup wizard** -- `agentdial setup` guides through identity creation and channel configuration
|
|
14
|
+
- **Secure credential storage** -- per-channel JSON files in `~/.agentdial/credentials/` with 0600 permissions
|
|
15
|
+
- **Voice support** -- Twilio-based voice calls with speech-to-text and text-to-speech
|
|
16
|
+
- **Rich responses** -- cards with images, action buttons (URL, callback, reply), and metadata
|
|
17
|
+
- **MCP server mode** -- `agentdial mcp-serve` integrates with Claude Code as a tool provider
|
|
18
|
+
- **Channel management CLI** -- add, remove, list, and test channels individually or all at once
|
|
19
|
+
- **Zod-validated schemas** -- all message types, configs, and identity files validated at runtime
|
|
20
|
+
- **Zero lock-in** -- agent backend is any HTTP endpoint that accepts JSON POST requests
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Naman Parikh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
# agentdial
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/agentdial)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](#supported-channels)
|
|
6
|
+
[](#tests)
|
|
7
|
+
[](https://www.npmjs.com/package/agentdial)
|
|
8
|
+
|
|
9
|
+
**Dial your AI agent into every platform.**
|
|
10
|
+
|
|
11
|
+
One identity file. Seven channels. Zero boilerplate.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx agentdial setup
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
___ __ ____ _ __
|
|
19
|
+
/ _ |___ ____ ___ ____/ / / __ \(_)___ _/ /
|
|
20
|
+
/ __ / _ `/ -_) _ \/ __/ / / / / / / _ `/ /
|
|
21
|
+
/_/ |_\_, /\__/_//_/\__/_/ /_/ /_/_/\_,_/_/
|
|
22
|
+
/___/
|
|
23
|
+
|
|
24
|
+
v1.0.0 One identity. Every channel.
|
|
25
|
+
|
|
26
|
+
┌────────────────────────────────────────┐
|
|
27
|
+
│ Agent Identity │
|
|
28
|
+
├────────────────────────────────────────┤
|
|
29
|
+
│ Name: Spark │
|
|
30
|
+
│ Tagline: Your AI concierge │
|
|
31
|
+
│ Backend: http://localhost:8080/agent │
|
|
32
|
+
└────────────────────────────────────────┘
|
|
33
|
+
|
|
34
|
+
Channel Status Cost Setup
|
|
35
|
+
──────────────── ──────── ─────── ─────
|
|
36
|
+
Telegram Bot active Free 2 min
|
|
37
|
+
Discord Bot active Free 3 min
|
|
38
|
+
Slack App ready Free 5 min
|
|
39
|
+
SMS (Twilio) ---- ~$0.01 5 min
|
|
40
|
+
Web Widget active Free 1 min
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
agentdial gives your AI agent a single identity file (`IDENTITY.md`) and connects it to Telegram, Discord, Slack, SMS, WhatsApp, email, and voice -- through one unified gateway.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install -g agentdial
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or run directly:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx agentdial setup
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Requirements:** Node.js >= 18 · **Supports:** macOS, Linux, Windows (WSL)
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
Three steps. Two minutes.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 1. Create your agent identity + pick channels
|
|
65
|
+
agentdial setup
|
|
66
|
+
|
|
67
|
+
# 2. Add a channel (interactive credential prompts)
|
|
68
|
+
agentdial channels add telegram
|
|
69
|
+
|
|
70
|
+
# 3. Start the gateway
|
|
71
|
+
agentdial serve --agent-url http://localhost:8080/agent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Your agent is now live on Telegram. Add more channels anytime with `agentdial channels add <channel>`.
|
|
75
|
+
|
|
76
|
+
## Why agentdial?
|
|
77
|
+
|
|
78
|
+
Every AI agent needs to talk to users. Today that means:
|
|
79
|
+
|
|
80
|
+
- **5-15 separate API integrations** (Telegram Bot API, Discord.js, Slack SDK, Twilio, SendGrid...)
|
|
81
|
+
- **Hundreds of lines of boilerplate** per channel (webhook setup, message normalization, response formatting)
|
|
82
|
+
- **No standard identity format** -- every platform represents your agent differently
|
|
83
|
+
- **Credential sprawl** -- API keys scattered across env files, dashboards, and config files
|
|
84
|
+
|
|
85
|
+
agentdial solves this with:
|
|
86
|
+
|
|
87
|
+
- **One identity file** (`IDENTITY.md`) that defines your agent's name, personality, and channel config
|
|
88
|
+
- **One gateway** that normalizes all incoming messages to a single `GatewayMessage` format
|
|
89
|
+
- **One response format** (`GatewayResponse`) that agentdial translates per-channel (Markdown for Telegram, embeds for Discord, blocks for Slack)
|
|
90
|
+
- **Secure credential storage** in `~/.agentdial/credentials/` with 0600 permissions
|
|
91
|
+
- **Zero lock-in** -- your agent backend is a plain HTTP endpoint that receives JSON
|
|
92
|
+
|
|
93
|
+
## Supported Channels
|
|
94
|
+
|
|
95
|
+
| Channel | Cost | Setup Time | Credentials Needed |
|
|
96
|
+
| ----------------- | -------------- | ---------- | -------------------------- |
|
|
97
|
+
| Telegram Bot | Free | 2 min | Bot token from @BotFather |
|
|
98
|
+
| Discord Bot | Free | 3 min | Bot token + application ID |
|
|
99
|
+
| Slack App | Free | 5 min | Bot token + signing secret |
|
|
100
|
+
| SMS (Twilio) | ~$0.0079/msg | 5 min | Account SID + auth token |
|
|
101
|
+
| WhatsApp (Twilio) | ~$0.005/msg | 10 min | Account SID + auth token |
|
|
102
|
+
| Email (SendGrid) | 60-day trial\* | 3 min | API key + verified sender |
|
|
103
|
+
| Voice (Twilio) | ~$0.013/min | 5 min | Account SID + auth token |
|
|
104
|
+
|
|
105
|
+
Free channels (Telegram, Discord) need zero payment info. Paid channels use Twilio or SendGrid with usage-based pricing. \*SendGrid free tier was removed May 2025; 60-day trial (100 emails/day), then $19.95/mo.
|
|
106
|
+
|
|
107
|
+
### Coming Soon
|
|
108
|
+
|
|
109
|
+
| Channel | Status |
|
|
110
|
+
| ------------------ | ------- |
|
|
111
|
+
| Microsoft Teams | Planned |
|
|
112
|
+
| Facebook Messenger | Planned |
|
|
113
|
+
| Web Widget | Planned |
|
|
114
|
+
|
|
115
|
+
## Architecture
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Telegram ──┐
|
|
119
|
+
Discord ──┤ ┌──────────────────┐
|
|
120
|
+
Slack ──┤ ┌────────────┐ │ │
|
|
121
|
+
SMS ──┼──>│ agentdial │──>│ Your Agent │
|
|
122
|
+
WhatsApp ──┤ │ Gateway │ │ Backend │
|
|
123
|
+
Email ──┤ │ :3141 │ │ (any HTTP) │
|
|
124
|
+
Voice ──┘ └────────────┘ └──────────────────┘
|
|
125
|
+
│
|
|
126
|
+
│ Normalizes all messages to:
|
|
127
|
+
│ { id, channel, from, text, timestamp }
|
|
128
|
+
│
|
|
129
|
+
│ Formats responses per-channel:
|
|
130
|
+
│ Telegram: Markdown + inline keyboards
|
|
131
|
+
│ Discord: Embeds + components
|
|
132
|
+
│ Slack: Blocks + actions
|
|
133
|
+
└ Others: Plain text fallback
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The gateway runs on port 3141 by default. Every incoming message from any channel is normalized into a `GatewayMessage`, forwarded to your agent backend as a POST request, and the response is formatted back into the channel's native format.
|
|
137
|
+
|
|
138
|
+
Your agent backend just needs one endpoint that accepts a JSON body and returns `{ text: "..." }`.
|
|
139
|
+
|
|
140
|
+
## IDENTITY.md Spec
|
|
141
|
+
|
|
142
|
+
agentdial introduces the **Agent Identity Protocol (AIP) v1.0** -- a single markdown file that defines your agent across all platforms.
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
---
|
|
146
|
+
name: spark
|
|
147
|
+
tagline: Your AI concierge
|
|
148
|
+
version: "1.0.0"
|
|
149
|
+
agent_url: http://localhost:8080/agent
|
|
150
|
+
channels:
|
|
151
|
+
telegram:
|
|
152
|
+
enabled: true
|
|
153
|
+
handle: "@spark_bot"
|
|
154
|
+
discord:
|
|
155
|
+
enabled: true
|
|
156
|
+
handle: "Spark#1234"
|
|
157
|
+
slack:
|
|
158
|
+
enabled: true
|
|
159
|
+
web:
|
|
160
|
+
enabled: true
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
# Spark
|
|
164
|
+
|
|
165
|
+
> Your AI concierge
|
|
166
|
+
|
|
167
|
+
## Personality
|
|
168
|
+
|
|
169
|
+
- Friendly and knowledgeable
|
|
170
|
+
- Concise but thorough
|
|
171
|
+
- Uses casual tone with professional substance
|
|
172
|
+
|
|
173
|
+
## Capabilities
|
|
174
|
+
|
|
175
|
+
- Restaurant recommendations and reservations
|
|
176
|
+
- Event discovery and booking
|
|
177
|
+
- Local area knowledge
|
|
178
|
+
|
|
179
|
+
## Boundaries
|
|
180
|
+
|
|
181
|
+
- No financial transactions
|
|
182
|
+
- No medical or legal advice
|
|
183
|
+
- No personal data retention beyond the session
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The YAML frontmatter is machine-readable. The markdown body is human-readable context your agent can use as a system prompt. The `channels` block declares which platforms your agent is active on.
|
|
187
|
+
|
|
188
|
+
## Claude Code Integration
|
|
189
|
+
|
|
190
|
+
agentdial ships as an MCP server for Claude Code. Add it to your project's `.mcp.json`:
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{
|
|
194
|
+
"mcpServers": {
|
|
195
|
+
"agentdial": {
|
|
196
|
+
"command": "npx",
|
|
197
|
+
"args": ["-y", "agentdial", "mcp-serve"]
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
This gives Claude Code tools to manage channels, test connections, and check agent status without leaving the terminal.
|
|
204
|
+
|
|
205
|
+
Start the MCP server standalone:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
agentdial mcp-serve
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Voice
|
|
212
|
+
|
|
213
|
+
Voice channels use Twilio for telephony. Configure with:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
agentdial voice setup
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
This prompts for your Twilio Account SID, Auth Token, and phone number. Test with:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
agentdial voice test --number +15551234567
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Voice calls are transcribed to text, sent through the same gateway pipeline as chat messages, and the response is synthesized back to speech via Twilio.
|
|
226
|
+
|
|
227
|
+
## Configuration
|
|
228
|
+
|
|
229
|
+
All config and credentials are stored locally:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
~/.agentdial/
|
|
233
|
+
├── config.json # Gateway port, log level, identity file path
|
|
234
|
+
├── credentials/ # Per-channel credential files (0600 permissions)
|
|
235
|
+
│ ├── telegram.json
|
|
236
|
+
│ ├── discord.json
|
|
237
|
+
│ ├── slack.json
|
|
238
|
+
│ └── twilio.json
|
|
239
|
+
├── templates/ # Identity file templates
|
|
240
|
+
└── logs/ # Gateway logs
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Example `config.json`:
|
|
244
|
+
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"identityFile": "IDENTITY.md",
|
|
248
|
+
"gatewayPort": 3141,
|
|
249
|
+
"logLevel": "info"
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Credentials are never stored in your project directory or committed to git. The `credentials/` directory is created with 0700 permissions, and individual credential files with 0600.
|
|
254
|
+
|
|
255
|
+
## All Commands
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
SETUP
|
|
259
|
+
agentdial setup Interactive wizard (identity + channels)
|
|
260
|
+
agentdial setup --file ./agent.md Use existing identity file
|
|
261
|
+
|
|
262
|
+
CHANNELS
|
|
263
|
+
agentdial channels add <channel> Configure a new channel
|
|
264
|
+
agentdial channels remove <channel> Remove a channel
|
|
265
|
+
agentdial channels list Show all channels and status
|
|
266
|
+
agentdial channels test [channel] Test one or all channels
|
|
267
|
+
|
|
268
|
+
VOICE
|
|
269
|
+
agentdial voice setup Configure Twilio voice
|
|
270
|
+
agentdial voice test -n <phone> Test call to a number
|
|
271
|
+
|
|
272
|
+
GATEWAY
|
|
273
|
+
agentdial serve Start the gateway (port 3141)
|
|
274
|
+
agentdial serve -p 8080 Custom port
|
|
275
|
+
agentdial serve -a http://my-agent Point to agent backend
|
|
276
|
+
|
|
277
|
+
STATUS
|
|
278
|
+
agentdial status Show all channel statuses
|
|
279
|
+
agentdial status --json Machine-readable output
|
|
280
|
+
|
|
281
|
+
TEST
|
|
282
|
+
agentdial test Send test message through gateway
|
|
283
|
+
agentdial test -c telegram -m "hi" Test specific channel
|
|
284
|
+
|
|
285
|
+
MCP
|
|
286
|
+
agentdial mcp-serve Start as MCP server for Claude Code
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Tests
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
cd tools/agentdial && pnpm test
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Tests cover identity parsing/validation, gateway message normalization, response formatting, adapter interface compliance, and Zod schema validation. All tests use mocks -- no real API calls.
|
|
296
|
+
|
|
297
|
+
## Contributing
|
|
298
|
+
|
|
299
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on adding adapters, running tests, and submitting PRs.
|
|
300
|
+
|
|
301
|
+
## See Also
|
|
302
|
+
|
|
303
|
+
- **[agentgrid](https://github.com/naman10parikh/agentgrid)** -- Spawn grids of AI coding agents in parallel terminal panes
|
|
304
|
+
- **[Energy](https://github.com/naman10parikh/Energy)** -- Self-improving agent platform. agentdial is part of the Energy toolkit
|
|
305
|
+
- **[Model Context Protocol](https://modelcontextprotocol.io)** -- The MCP standard agentdial integrates with
|
|
306
|
+
- **[Google A2A](https://google.github.io/A2A/)** -- Agent-to-Agent protocol for inter-agent communication
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
MIT -- see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ChannelAdapter, ChannelConfig, ChannelStatus, GatewayMessage, GatewayResponse } from "./types.js";
|
|
2
|
+
export declare class DiscordAdapter implements ChannelAdapter {
|
|
3
|
+
readonly name: "discord";
|
|
4
|
+
readonly displayName: string;
|
|
5
|
+
readonly free = true;
|
|
6
|
+
readonly setupTime: string;
|
|
7
|
+
private client;
|
|
8
|
+
private token;
|
|
9
|
+
private messageHandler;
|
|
10
|
+
private connectedAt;
|
|
11
|
+
private lastMessageAt;
|
|
12
|
+
private loadDiscordJs;
|
|
13
|
+
setup(config: ChannelConfig): Promise<void>;
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
send(to: string, response: GatewayResponse): Promise<void>;
|
|
17
|
+
onMessage(handler: (msg: GatewayMessage) => Promise<GatewayResponse>): void;
|
|
18
|
+
test(): Promise<{
|
|
19
|
+
ok: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
}>;
|
|
22
|
+
status(): Promise<ChannelStatus>;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=discord.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../src/adapters/discord.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AA+BpB,qBAAa,cAAe,YAAW,cAAc;IACnD,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IACnC,QAAQ,CAAC,WAAW,SAAiC;IACrD,QAAQ,CAAC,IAAI,QAAQ;IACrB,QAAQ,CAAC,SAAS,SAA+B;IAEjD,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,cAAc,CAEN;IAChB,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,aAAa,CAAuB;YAE9B,aAAa;IAgBrB,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAW3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA+CxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAchE,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAIrE,IAAI,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAehD,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;CAUvC"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { getCredential, saveCredential } from "../lib/credentials.js";
|
|
2
|
+
import { CHANNEL_DISPLAY_NAMES, CHANNEL_SETUP_TIMES, } from "../lib/constants.js";
|
|
3
|
+
export class DiscordAdapter {
|
|
4
|
+
name = "discord";
|
|
5
|
+
displayName = CHANNEL_DISPLAY_NAMES.discord;
|
|
6
|
+
free = true;
|
|
7
|
+
setupTime = CHANNEL_SETUP_TIMES.discord;
|
|
8
|
+
client = null;
|
|
9
|
+
token = null;
|
|
10
|
+
messageHandler = null;
|
|
11
|
+
connectedAt = null;
|
|
12
|
+
lastMessageAt = null;
|
|
13
|
+
async loadDiscordJs() {
|
|
14
|
+
try {
|
|
15
|
+
const pkg = "discord.js";
|
|
16
|
+
const mod = (await import(/* webpackIgnore: true */ pkg));
|
|
17
|
+
return mod;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw new Error("discord.js not installed. Run: npm install discord.js");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async setup(config) {
|
|
24
|
+
const token = config.credentials?.["bot_token"];
|
|
25
|
+
if (!token)
|
|
26
|
+
throw new Error("Missing credential: bot_token. Create a bot at discord.com/developers/applications.");
|
|
27
|
+
await this.loadDiscordJs();
|
|
28
|
+
this.token = token;
|
|
29
|
+
await saveCredential("discord", "bot_token", token);
|
|
30
|
+
}
|
|
31
|
+
async connect() {
|
|
32
|
+
if (!this.token) {
|
|
33
|
+
const stored = await getCredential("discord", "bot_token");
|
|
34
|
+
if (!stored)
|
|
35
|
+
throw new Error("Not configured. Run setup() first.");
|
|
36
|
+
this.token = stored;
|
|
37
|
+
}
|
|
38
|
+
const { Client, GatewayIntentBits } = await this.loadDiscordJs();
|
|
39
|
+
this.client = new Client({
|
|
40
|
+
intents: [
|
|
41
|
+
GatewayIntentBits.Guilds,
|
|
42
|
+
GatewayIntentBits.GuildMessages,
|
|
43
|
+
GatewayIntentBits.MessageContent,
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
this.client.on("messageCreate", (raw) => {
|
|
47
|
+
const message = raw;
|
|
48
|
+
if (message.author.bot || !this.messageHandler)
|
|
49
|
+
return;
|
|
50
|
+
this.lastMessageAt = Date.now();
|
|
51
|
+
const attachments = [...message.attachments.values()].map((a) => ({
|
|
52
|
+
type: "file",
|
|
53
|
+
url: a.url,
|
|
54
|
+
name: a.name,
|
|
55
|
+
mimeType: a.contentType ?? undefined,
|
|
56
|
+
}));
|
|
57
|
+
const msg = {
|
|
58
|
+
id: message.id,
|
|
59
|
+
channel: "discord",
|
|
60
|
+
from: message.author.username,
|
|
61
|
+
text: message.content,
|
|
62
|
+
timestamp: message.createdTimestamp,
|
|
63
|
+
threadId: message.channelId,
|
|
64
|
+
replyTo: message.reference?.messageId,
|
|
65
|
+
attachments: attachments.length ? attachments : undefined,
|
|
66
|
+
metadata: { guildId: message.guildId, channelId: message.channelId },
|
|
67
|
+
};
|
|
68
|
+
this.messageHandler(msg)
|
|
69
|
+
.then((response) => {
|
|
70
|
+
this.send(message.channelId, response).catch(() => { });
|
|
71
|
+
})
|
|
72
|
+
.catch(() => { });
|
|
73
|
+
});
|
|
74
|
+
await this.client.login(this.token);
|
|
75
|
+
this.connectedAt = Date.now();
|
|
76
|
+
}
|
|
77
|
+
async disconnect() {
|
|
78
|
+
if (this.client) {
|
|
79
|
+
await this.client.destroy();
|
|
80
|
+
this.client = null;
|
|
81
|
+
}
|
|
82
|
+
this.connectedAt = null;
|
|
83
|
+
}
|
|
84
|
+
async send(to, response) {
|
|
85
|
+
if (!this.client)
|
|
86
|
+
throw new Error("Not connected");
|
|
87
|
+
const channel = await this.client.channels.fetch(to);
|
|
88
|
+
let content = response.text;
|
|
89
|
+
if (response.cards?.length) {
|
|
90
|
+
for (const card of response.cards) {
|
|
91
|
+
content += `\n\n**${card.title}**`;
|
|
92
|
+
if (card.description)
|
|
93
|
+
content += `\n${card.description}`;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (content.length > 2000)
|
|
97
|
+
content = content.slice(0, 1997) + "...";
|
|
98
|
+
await channel.send({ content });
|
|
99
|
+
}
|
|
100
|
+
onMessage(handler) {
|
|
101
|
+
this.messageHandler = handler;
|
|
102
|
+
}
|
|
103
|
+
async test() {
|
|
104
|
+
try {
|
|
105
|
+
if (!this.client?.isReady())
|
|
106
|
+
return { ok: false, error: "Bot not connected" };
|
|
107
|
+
const tag = this.client.user?.tag ?? "unknown";
|
|
108
|
+
const guilds = this.client.guilds.cache.size;
|
|
109
|
+
return { ok: true, error: undefined };
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
error: err instanceof Error ? err.message : "Unknown error",
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async status() {
|
|
119
|
+
const connected = this.client?.isReady() ?? false;
|
|
120
|
+
return {
|
|
121
|
+
channel: "discord",
|
|
122
|
+
connected,
|
|
123
|
+
latencyMs: connected ? this.client.ws.ping : null,
|
|
124
|
+
lastMessage: this.lastMessageAt,
|
|
125
|
+
error: connected ? null : "Not connected",
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=discord.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discord.js","sourceRoot":"","sources":["../../src/adapters/discord.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ChannelAdapter, ChannelConfig, ChannelStatus, GatewayMessage, GatewayResponse } from "./types.js";
|
|
2
|
+
interface InboundParsePayload {
|
|
3
|
+
from: string;
|
|
4
|
+
to: string;
|
|
5
|
+
subject: string;
|
|
6
|
+
text: string;
|
|
7
|
+
html?: string;
|
|
8
|
+
attachments?: string;
|
|
9
|
+
"attachment-info"?: string;
|
|
10
|
+
[key: string]: string | undefined;
|
|
11
|
+
}
|
|
12
|
+
export declare class EmailAdapter implements ChannelAdapter {
|
|
13
|
+
readonly name: "email";
|
|
14
|
+
readonly displayName = "Email (SendGrid)";
|
|
15
|
+
readonly free = false;
|
|
16
|
+
readonly cost = "100/day free, then $0.001/msg";
|
|
17
|
+
readonly setupTime = "3 min";
|
|
18
|
+
private apiKey;
|
|
19
|
+
private fromEmail;
|
|
20
|
+
private fromName;
|
|
21
|
+
private messageHandler;
|
|
22
|
+
private connected;
|
|
23
|
+
private lastMessageTs;
|
|
24
|
+
setup(config: ChannelConfig): Promise<void>;
|
|
25
|
+
connect(): Promise<void>;
|
|
26
|
+
disconnect(): Promise<void>;
|
|
27
|
+
send(to: string, response: GatewayResponse): Promise<void>;
|
|
28
|
+
onMessage(handler: (msg: GatewayMessage) => Promise<GatewayResponse>): void;
|
|
29
|
+
/** Call from HTTP webhook handler with parsed SendGrid Inbound Parse POST body. */
|
|
30
|
+
handleWebhook(payload: InboundParsePayload): Promise<GatewayResponse | null>;
|
|
31
|
+
test(): Promise<{
|
|
32
|
+
ok: boolean;
|
|
33
|
+
error?: string;
|
|
34
|
+
}>;
|
|
35
|
+
status(): Promise<ChannelStatus>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/adapters/email.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAC;AAapB,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CACnC;AA+DD,qBAAa,YAAa,YAAW,cAAc;IACjD,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAU;IACjC,QAAQ,CAAC,WAAW,sBAAsB;IAC1C,QAAQ,CAAC,IAAI,SAAS;IACtB,QAAQ,CAAC,IAAI,mCAAmC;IAChD,QAAQ,CAAC,SAAS,WAAW;IAE7B,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,QAAQ,CAAM;IACtB,OAAO,CAAC,cAAc,CAEN;IAChB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAuB;IAEtC,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA0B3C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAI3B,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BhE,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI;IAI3E,mFAAmF;IAC7E,aAAa,CACjB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAwB5B,IAAI,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAehD,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC;CAqBvC"}
|