@xmtp/agent-sdk 0.0.3 → 0.0.5
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 +181 -17
- package/dist/bin/generateKeys.d.ts +2 -0
- package/dist/bin/generateKeys.js +35 -0
- package/dist/bin/generateKeys.js.map +1 -0
- package/dist/core/Agent.d.ts +6 -5
- package/dist/core/Agent.js +47 -9
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/AgentContext.d.ts +3 -0
- package/dist/core/AgentContext.js +14 -0
- package/dist/core/AgentContext.js.map +1 -1
- package/dist/demo.js +22 -19
- package/dist/demo.js.map +1 -1
- package/dist/middleware/CommandRouter.d.ts +10 -0
- package/dist/middleware/CommandRouter.js +45 -0
- package/dist/middleware/CommandRouter.js.map +1 -0
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/utils/crypto.d.ts +19 -0
- package/dist/utils/crypto.js +55 -0
- package/dist/utils/crypto.js.map +1 -0
- package/dist/utils/debug.d.ts +10 -0
- package/dist/utils/debug.js +53 -0
- package/dist/utils/debug.js.map +1 -0
- package/dist/utils/filter.d.ts +19 -1
- package/dist/utils/filter.js +15 -0
- package/dist/utils/filter.js.map +1 -1
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/message.d.ts +35 -0
- package/dist/utils/message.js +30 -0
- package/dist/utils/message.js.map +1 -0
- package/package.json +14 -6
package/README.md
CHANGED
|
@@ -1,48 +1,212 @@
|
|
|
1
|
-
# XMTP Agent SDK
|
|
1
|
+
# XMTP Agent SDK
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
To keep up with the latest SDK developments, see the [Issues tab](https://github.com/xmtp/xmtp-js/issues) in this repo.
|
|
3
|
+
Build event‑driven, middleware‑powered messaging agents on the XMTP network. 🚀
|
|
6
4
|
|
|
7
5
|
> [!CAUTION]
|
|
8
6
|
> This SDK is in beta status and ready for you to build with in production. Software in this status may change based on feedback.
|
|
9
7
|
|
|
10
|
-
##
|
|
8
|
+
## Documentation
|
|
9
|
+
|
|
10
|
+
Full agent building guide: **[Build an XMTP Agent](https://docs.xmtp.org/agents/get-started/build-an-agent)**
|
|
11
|
+
|
|
12
|
+
This SDK is based on familiar Node.js patterns: you register event listeners, compose middleware, and extend behavior just like you would in frameworks such as [Express](https://expressjs.com/). This makes it easy to bring existing JavaScript and TypeScript skills into building conversational agents.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Choose your package manager:
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
```bash
|
|
19
|
+
npm install @xmtp/agent-sdk
|
|
20
|
+
# or
|
|
21
|
+
pnpm add @xmtp/agent-sdk
|
|
22
|
+
# or
|
|
23
|
+
yarn add @xmtp/agent-sdk
|
|
24
|
+
```
|
|
13
25
|
|
|
14
|
-
|
|
26
|
+
## Quick Start
|
|
15
27
|
|
|
16
28
|
```ts
|
|
29
|
+
import { Agent, createSigner, createUser } from "@xmtp/agent-sdk";
|
|
30
|
+
|
|
31
|
+
// 1. Create a local user + signer (you can plug in your own wallet signer)
|
|
32
|
+
const user = createUser();
|
|
33
|
+
const signer = createSigner(user);
|
|
34
|
+
|
|
35
|
+
// 2. Spin up the agent
|
|
36
|
+
const agent = await Agent.create(signer, {
|
|
37
|
+
env: "dev", // or 'production'
|
|
38
|
+
dbPath: null, // in-memory store; provide a path to persist
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 3. Respond to any incoming message
|
|
17
42
|
agent.on("message", async (ctx) => {
|
|
18
|
-
await ctx.conversation.send("Hello!");
|
|
43
|
+
await ctx.conversation.send("Hello from my XMTP Agent! 👋");
|
|
19
44
|
});
|
|
45
|
+
|
|
46
|
+
// 4. Log when we're ready
|
|
47
|
+
agent.on("start", () => {
|
|
48
|
+
const address = agent.client.accountIdentifier?.identifier;
|
|
49
|
+
const env = agent.client.options?.env;
|
|
50
|
+
console.log(`Agent online: http://xmtp.chat/dm/${address}?env=${env}`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await agent.start();
|
|
20
54
|
```
|
|
21
55
|
|
|
22
|
-
|
|
56
|
+
## Environment Variables
|
|
57
|
+
|
|
58
|
+
The XMTP Agent SDK supports environment variables (`process.env`) to simplify configuration without code changes.
|
|
59
|
+
|
|
60
|
+
**Available Variables:**
|
|
23
61
|
|
|
24
|
-
|
|
62
|
+
| Variable | Purpose | Example |
|
|
63
|
+
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
|
|
64
|
+
| `XMTP_WALLET_KEY` | [Private key for wallet](https://docs.xmtp.org/inboxes/core-messaging/create-a-signer) | `XMTP_WALLET_KEY=0x1234...abcd` |
|
|
65
|
+
| `XMTP_ENV` | [Network environment](https://docs.xmtp.org/agents/core-messaging/create-a-client#xmtp-network-environments) | `XMTP_ENV=dev` or `XMTP_ENV=production` |
|
|
66
|
+
| `XMTP_DB_ENCRYPTION_KEY` | [Database encryption key](https://docs.xmtp.org/agents/core-messaging/create-a-client#keep-the-database-encryption-key-safe) | `XMTP_DB_ENCRYPTION_KEY=0xabcd...1234` |
|
|
67
|
+
| `XMTP_FORCE_DEBUG` | [Activate debugging logs](https://docs.xmtp.org/agents/debug-agents) | `XMTP_FORCE_DEBUG=true` |
|
|
68
|
+
| `XMTP_FORCE_REVOKE_INSTALLATIONS` | [Remove other installations](https://docs.xmtp.org/agents/core-messaging/agent-installations#revoke-agent-installations) | `XMTP_FORCE_REVOKE_INSTALLATIONS=true` |
|
|
69
|
+
|
|
70
|
+
Using the environment variables, you can setup your agent in just a few lines of code:
|
|
25
71
|
|
|
26
72
|
```ts
|
|
73
|
+
// Load variables from .env file
|
|
74
|
+
process.loadEnvFile(".env");
|
|
75
|
+
|
|
76
|
+
// Create agent using environment variables
|
|
77
|
+
const agent = await Agent.create();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Core Concepts
|
|
81
|
+
|
|
82
|
+
### 1. Event‑Driven Architecture
|
|
83
|
+
|
|
84
|
+
Subscribe only to what you need using Node’s `EventEmitter` interface.
|
|
85
|
+
|
|
86
|
+
Events you can listen for:
|
|
87
|
+
|
|
88
|
+
- `message` – a new incoming (non‑self) message
|
|
89
|
+
- `start` / `stop` – lifecycle events
|
|
90
|
+
- `error` – surfaced errors
|
|
91
|
+
|
|
92
|
+
**Example:**
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
agent.on("error", (error) => {
|
|
96
|
+
console.error("Agent error", error);
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 2. Middleware Support
|
|
101
|
+
|
|
102
|
+
Extend your agent with custom business logic using middlewares. Compose cross-cutting behavior like routing, telemetry, rate limiting, analytics, and feature flags, or plug in your own.
|
|
103
|
+
|
|
104
|
+
**Example:**
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import { CommandRouter } from "@xmtp/agent-sdk";
|
|
108
|
+
|
|
27
109
|
const router = new CommandRouter();
|
|
28
110
|
|
|
29
|
-
router.command("/
|
|
30
|
-
await ctx.conversation.send(
|
|
111
|
+
router.command("/version", async (ctx) => {
|
|
112
|
+
await ctx.conversation.send(`v${process.env.npm_package_version}`);
|
|
31
113
|
});
|
|
32
114
|
|
|
33
|
-
const agent = new Agent({ client });
|
|
34
115
|
agent.use(router.middleware());
|
|
35
116
|
```
|
|
36
117
|
|
|
37
|
-
### Built
|
|
118
|
+
### 3. Built‑in Filters
|
|
119
|
+
|
|
120
|
+
Instead of manually checking every incoming message, you can compose simple, reusable filters that make intent clear.
|
|
38
121
|
|
|
39
|
-
|
|
122
|
+
**Example:**
|
|
40
123
|
|
|
41
124
|
```ts
|
|
125
|
+
import { withFilter, filter } from "@xmtp/agent-sdk";
|
|
126
|
+
|
|
127
|
+
// Using filter in message handler
|
|
42
128
|
agent.on(
|
|
43
129
|
"message",
|
|
44
|
-
withFilter(filter.
|
|
45
|
-
await ctx.conversation.send("
|
|
130
|
+
withFilter(filter.startsWith("@agent"), async (ctx) => {
|
|
131
|
+
await ctx.conversation.send("How can I help you?");
|
|
46
132
|
}),
|
|
47
133
|
);
|
|
134
|
+
|
|
135
|
+
// Combination of filters
|
|
136
|
+
const combined = filter.and(filter.notFromSelf, filter.textOnly);
|
|
137
|
+
|
|
138
|
+
agent.on(
|
|
139
|
+
"message",
|
|
140
|
+
withFilter(combined, async (ctx) => {
|
|
141
|
+
await ctx.conversation.send("You sent a text message ✅");
|
|
142
|
+
}),
|
|
143
|
+
);
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
For convenience, the `filter` object can also be imported as `f`:
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
// You can import either name:
|
|
150
|
+
import { filter, f } from "@xmtp/agent-sdk";
|
|
151
|
+
|
|
152
|
+
// Both work the same way:
|
|
153
|
+
const longVersion = filter.and(filter.notFromSelf, filter.textOnly);
|
|
154
|
+
const shortVersion = f.and(f.notFromSelf, f.textOnly);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
You can find all available prebuilt filters [here](https://github.com/xmtp/xmtp-js/blob/main/sdks/agent-sdk/src/utils/filter.ts).
|
|
158
|
+
|
|
159
|
+
### 4. Rich Context
|
|
160
|
+
|
|
161
|
+
Every `message` handler receives an `AgentContext` with:
|
|
162
|
+
|
|
163
|
+
- `message` – decoded message
|
|
164
|
+
- `conversation` – the active conversation object
|
|
165
|
+
- `client` – underlying XMTP client
|
|
166
|
+
- Helpers like `sendText()` / `sendTextReply()`
|
|
167
|
+
|
|
168
|
+
**Example:**
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
agent.on("message", async (ctx) => {
|
|
172
|
+
await ctx.sendTextReply("Reply using helper ✨");
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Adding Custom Content Types
|
|
177
|
+
|
|
178
|
+
Pass codecs when creating your agent to extend supported content:
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { ReplyCodec } from "@xmtp/content-type-reply";
|
|
182
|
+
|
|
183
|
+
const agent = await Agent.create(signer, {
|
|
184
|
+
env: "dev",
|
|
185
|
+
dbPath: null,
|
|
186
|
+
codecs: [new ReplyCodec()],
|
|
187
|
+
});
|
|
48
188
|
```
|
|
189
|
+
|
|
190
|
+
## Debugging
|
|
191
|
+
|
|
192
|
+
- [Debug an agent](https://docs.xmtp.org/agents/debug-agents)
|
|
193
|
+
- [Further debugging info](https://docs.xmtp.org/inboxes/debug-your-app#debug-your-inbox-app)
|
|
194
|
+
|
|
195
|
+
## FAQ (Quick Hits)
|
|
196
|
+
|
|
197
|
+
| Question | Answer |
|
|
198
|
+
| -------------------------------------------------------------------------------------------- | ----------------------------------------------- |
|
|
199
|
+
| Does middleware run for every message? | Yes, in the order added. |
|
|
200
|
+
| How do I reject a message early? | Don’t call `next()` in middleware. |
|
|
201
|
+
| How do I filter messages? | Use `withFilter(...)` around an event listener. |
|
|
202
|
+
| Can I send custom [content types](https://docs.xmtp.org/agents/content-types/content-types)? | Yes, register codecs during agent creation. |
|
|
203
|
+
|
|
204
|
+
## Contributing / Feedback
|
|
205
|
+
|
|
206
|
+
We’d love your feedback: [open an issue](https://github.com/xmtp/xmtp-js/issues) or discussion. PRs welcome for docs, examples, and core improvements.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
Build something delightful. Then tell us what you wish was easier.
|
|
211
|
+
|
|
212
|
+
Happy hacking 💫
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { generateClientKeys } from "../utils/crypto.js";
|
|
5
|
+
/**
|
|
6
|
+
* Generates client keys and saves them to a .env file in the project root.
|
|
7
|
+
* This script creates the necessary environment variables for XMTP agent initialization.
|
|
8
|
+
*/
|
|
9
|
+
function main() {
|
|
10
|
+
try {
|
|
11
|
+
// Generate the client keys
|
|
12
|
+
const keys = generateClientKeys();
|
|
13
|
+
// Create the .env file content
|
|
14
|
+
const envContent = Object.entries(keys)
|
|
15
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
16
|
+
.join("\n") + "\n";
|
|
17
|
+
if (!process.env.INIT_CWD) {
|
|
18
|
+
throw new Error(`Cannot invoke script because "process.env.INIT_CWD" wasn't found.`);
|
|
19
|
+
}
|
|
20
|
+
const envFilePath = join(process.env.INIT_CWD, ".env");
|
|
21
|
+
writeFileSync(envFilePath, envContent, "utf8");
|
|
22
|
+
console.log("✅ Successfully generated client keys and saved to .env file");
|
|
23
|
+
console.log(`📁 File location: ${envFilePath}`);
|
|
24
|
+
console.log("🔑 Generated keys:");
|
|
25
|
+
Object.keys(keys).forEach((key) => {
|
|
26
|
+
console.log(` - ${key}`);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error("❌ Error generating client keys:", error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
main();
|
|
35
|
+
//# sourceMappingURL=generateKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateKeys.js","sourceRoot":"","sources":["../../src/bin/generateKeys.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;GAGG;AACH,SAAS,IAAI;IACX,IAAI,CAAC;QACH,2BAA2B;QAC3B,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAC;QAElC,+BAA+B;QAC/B,MAAM,UAAU,GACd,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;aACjB,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC;aACxC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QAEvB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;QACJ,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAEvD,aAAa,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAE/C,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,qBAAqB,WAAW,EAAE,CAAC,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/core/Agent.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
2
|
import type { ContentCodec } from "@xmtp/content-type-primitives";
|
|
3
|
+
import { ReactionCodec } from "@xmtp/content-type-reaction";
|
|
4
|
+
import { RemoteAttachmentCodec } from "@xmtp/content-type-remote-attachment";
|
|
5
|
+
import { ReplyCodec } from "@xmtp/content-type-reply";
|
|
3
6
|
import { Client, type ClientOptions } from "@xmtp/node-sdk";
|
|
4
7
|
import { AgentContext } from "./AgentContext.js";
|
|
5
8
|
interface EventHandlerMap<ContentTypes> {
|
|
@@ -11,16 +14,14 @@ interface EventHandlerMap<ContentTypes> {
|
|
|
11
14
|
export interface AgentOptions<ContentTypes> {
|
|
12
15
|
client: Client<ContentTypes>;
|
|
13
16
|
}
|
|
17
|
+
export type AgentEventHandler<ContentTypes = unknown> = (ctx: AgentContext<ContentTypes>) => Promise<void> | void;
|
|
14
18
|
export type AgentMiddleware<ContentTypes> = (ctx: AgentContext<ContentTypes>, next: () => Promise<void>) => Promise<void>;
|
|
15
19
|
export declare class Agent<ContentTypes> extends EventEmitter<EventHandlerMap<ContentTypes>> {
|
|
16
20
|
#private;
|
|
17
21
|
constructor({ client }: AgentOptions<ContentTypes>);
|
|
18
|
-
static create<ContentCodecs extends ContentCodec[] = []>(signer
|
|
22
|
+
static create<ContentCodecs extends ContentCodec[] = []>(signer?: Parameters<typeof Client.create>[0], options?: Omit<ClientOptions, "codecs"> & {
|
|
19
23
|
codecs?: ContentCodecs;
|
|
20
|
-
}): Promise<Agent<import("@xmtp/node-sdk").ExtractCodecContentTypes<ContentCodecs>>>;
|
|
21
|
-
static build<ContentCodecs extends ContentCodec[] = []>(identifier: Parameters<typeof Client.build>[0], options?: Omit<ClientOptions, "codecs"> & {
|
|
22
|
-
codecs?: ContentCodecs;
|
|
23
|
-
}): Promise<Agent<import("@xmtp/node-sdk").ExtractCodecContentTypes<ContentCodecs>>>;
|
|
24
|
+
}): Promise<Agent<import("@xmtp/node-sdk").ExtractCodecContentTypes<(ReactionCodec | ReplyCodec | RemoteAttachmentCodec | (never[] | ContentCodecs)[number])[]>>>;
|
|
24
25
|
use(middleware: AgentMiddleware<ContentTypes>): this;
|
|
25
26
|
start(): Promise<void>;
|
|
26
27
|
get client(): Client<ContentTypes>;
|
package/dist/core/Agent.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import EventEmitter from "node:events";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { ReactionCodec } from "@xmtp/content-type-reaction";
|
|
3
|
+
import { RemoteAttachmentCodec } from "@xmtp/content-type-remote-attachment";
|
|
4
|
+
import { ReplyCodec } from "@xmtp/content-type-reply";
|
|
5
|
+
import { ApiUrls, Client, } from "@xmtp/node-sdk";
|
|
6
|
+
import { isHex } from "viem/utils";
|
|
7
|
+
import { getEncryptionKeyFromHex } from "../utils/crypto.js";
|
|
8
|
+
import { logDetails } from "../utils/debug.js";
|
|
9
|
+
import { filter } from "../utils/filter.js";
|
|
10
|
+
import { createSigner, createUser } from "../utils/user.js";
|
|
4
11
|
import { AgentContext } from "./AgentContext.js";
|
|
5
12
|
export class Agent extends EventEmitter {
|
|
6
13
|
#client;
|
|
@@ -13,13 +20,44 @@ export class Agent extends EventEmitter {
|
|
|
13
20
|
static async create(signer,
|
|
14
21
|
// Note: we need to omit this so that "Client.create" can correctly infer the codecs.
|
|
15
22
|
options) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
if (!signer) {
|
|
24
|
+
if (isHex(process.env.XMTP_WALLET_KEY)) {
|
|
25
|
+
signer = createSigner(createUser(process.env.XMTP_WALLET_KEY));
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
throw new Error(`No signer detected. Provide a "signer" to "Agent.create()" or set the "XMTP_WALLET_KEY" environment variable to a private key in hexadecimal format. Read more: https://docs.xmtp.org/inboxes/core-messaging/create-a-signer`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const initializedOptions = { ...options };
|
|
32
|
+
initializedOptions.appVersion ??= "agent-sdk/alpha";
|
|
33
|
+
if (process.env.XMTP_DB_ENCRYPTION_KEY) {
|
|
34
|
+
initializedOptions.dbEncryptionKey = getEncryptionKeyFromHex(process.env.XMTP_DB_ENCRYPTION_KEY);
|
|
35
|
+
}
|
|
36
|
+
if (process.env.XMTP_ENV &&
|
|
37
|
+
Object.keys(ApiUrls).includes(process.env.XMTP_ENV)) {
|
|
38
|
+
initializedOptions.env = process.env.XMTP_ENV;
|
|
39
|
+
}
|
|
40
|
+
if (process.env.XMTP_FORCE_DEBUG) {
|
|
41
|
+
initializedOptions.debugEventsEnabled = true;
|
|
42
|
+
initializedOptions.loggingLevel = "warn" /* LogLevel.warn */;
|
|
43
|
+
initializedOptions.structuredLogging = true;
|
|
44
|
+
}
|
|
45
|
+
const upgradedCodecs = [
|
|
46
|
+
...(initializedOptions.codecs ?? []),
|
|
47
|
+
new ReactionCodec(),
|
|
48
|
+
new ReplyCodec(),
|
|
49
|
+
new RemoteAttachmentCodec(),
|
|
50
|
+
];
|
|
51
|
+
const client = await Client.create(signer, {
|
|
52
|
+
...initializedOptions,
|
|
53
|
+
codecs: upgradedCodecs,
|
|
54
|
+
});
|
|
55
|
+
if (process.env.XMTP_FORCE_REVOKE_INSTALLATIONS) {
|
|
56
|
+
await client.revokeAllOtherInstallations();
|
|
57
|
+
}
|
|
58
|
+
if (process.env.XMTP_FORCE_DEBUG) {
|
|
59
|
+
await logDetails(client);
|
|
60
|
+
}
|
|
23
61
|
return new Agent({ client });
|
|
24
62
|
}
|
|
25
63
|
use(middleware) {
|
package/dist/core/Agent.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Agent.js","sourceRoot":"","sources":["../../src/core/Agent.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,MAAM,
|
|
1
|
+
{"version":3,"file":"Agent.js","sourceRoot":"","sources":["../../src/core/Agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { type Reaction } from "@xmtp/content-type-reaction";
|
|
1
2
|
import type { Client, Conversation, DecodedMessage } from "@xmtp/node-sdk";
|
|
2
3
|
export declare class AgentContext<ContentTypes = unknown> {
|
|
3
4
|
#private;
|
|
4
5
|
constructor(message: DecodedMessage<ContentTypes>, conversation: Conversation, client: Client<ContentTypes>);
|
|
6
|
+
sendReaction(content: string, schema: Reaction["schema"]): Promise<void>;
|
|
5
7
|
sendText(text: string): Promise<void>;
|
|
6
8
|
sendTextReply(text: string): Promise<void>;
|
|
9
|
+
getOwnAddress(): string | undefined;
|
|
7
10
|
getSenderAddress(): Promise<string>;
|
|
8
11
|
get message(): DecodedMessage<ContentTypes>;
|
|
9
12
|
get conversation(): Conversation<unknown>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ContentTypeReaction, } from "@xmtp/content-type-reaction";
|
|
1
2
|
import { ContentTypeReply } from "@xmtp/content-type-reply";
|
|
2
3
|
import { ContentTypeText } from "@xmtp/content-type-text";
|
|
3
4
|
export class AgentContext {
|
|
@@ -9,6 +10,16 @@ export class AgentContext {
|
|
|
9
10
|
this.#conversation = conversation;
|
|
10
11
|
this.#client = client;
|
|
11
12
|
}
|
|
13
|
+
async sendReaction(content, schema) {
|
|
14
|
+
const reaction = {
|
|
15
|
+
action: "added",
|
|
16
|
+
reference: this.#message.id,
|
|
17
|
+
referenceInboxId: this.#message.senderInboxId,
|
|
18
|
+
schema,
|
|
19
|
+
content,
|
|
20
|
+
};
|
|
21
|
+
await this.#conversation.send(reaction, ContentTypeReaction);
|
|
22
|
+
}
|
|
12
23
|
async sendText(text) {
|
|
13
24
|
await this.#conversation.send(text, ContentTypeText);
|
|
14
25
|
}
|
|
@@ -21,6 +32,9 @@ export class AgentContext {
|
|
|
21
32
|
};
|
|
22
33
|
await this.#conversation.send(reply, ContentTypeReply);
|
|
23
34
|
}
|
|
35
|
+
getOwnAddress() {
|
|
36
|
+
return this.#client.accountIdentifier?.identifier;
|
|
37
|
+
}
|
|
24
38
|
async getSenderAddress() {
|
|
25
39
|
const inboxState = await this.#client.preferences.inboxStateFromInboxIds([
|
|
26
40
|
this.#message.senderInboxId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentContext.js","sourceRoot":"","sources":["../../src/core/AgentContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAc,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,OAAO,YAAY;IACvB,OAAO,CAAuB;IAC9B,QAAQ,CAA+B;IACvC,aAAa,CAAe;IAE5B,YACE,OAAqC,EACrC,YAA0B,EAC1B,MAA4B;QAE5B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,MAAM,KAAK,GAAU;YACnB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC3B,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa;YAC7C,WAAW,EAAE,eAAe;YAC5B,OAAO,EAAE,IAAI;SACd,CAAC;QACF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC;YACvE,IAAI,CAAC,QAAQ,CAAC,aAAa;SAC5B,CAAC,CAAC;QACH,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACjD,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"AgentContext.js","sourceRoot":"","sources":["../../src/core/AgentContext.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAEpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAc,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,OAAO,YAAY;IACvB,OAAO,CAAuB;IAC9B,QAAQ,CAA+B;IACvC,aAAa,CAAe;IAE5B,YACE,OAAqC,EACrC,YAA0B,EAC1B,MAA4B;QAE5B,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;QAClC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,OAAe,EAAE,MAA0B;QAC5D,MAAM,QAAQ,GAAa;YACzB,MAAM,EAAE,OAAO;YACf,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC3B,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa;YAC7C,MAAM;YACN,OAAO;SACR,CAAC;QACF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,IAAY;QAC9B,MAAM,KAAK,GAAU;YACnB,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE;YAC3B,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,aAAa;YAC7C,WAAW,EAAE,eAAe;YAC5B,OAAO,EAAE,IAAI;SACd,CAAC;QACF,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,gBAAgB,CAAC,CAAC;IACzD,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,UAAU,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,gBAAgB;QACpB,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,sBAAsB,CAAC;YACvE,IAAI,CAAC,QAAQ,CAAC,aAAa;SAC5B,CAAC,CAAC;QACH,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACjD,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;CACF"}
|
package/dist/demo.js
CHANGED
|
@@ -1,33 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadEnvFile } from "node:process";
|
|
2
2
|
import { Agent } from "./core/index.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
import { CommandRouter } from "./middleware/CommandRouter.js";
|
|
4
|
+
import { getTestUrl } from "./utils/debug.js";
|
|
5
|
+
import { createSigner, createUser, f, withFilter } from "./utils/index.js";
|
|
6
|
+
try {
|
|
7
|
+
loadEnvFile(".env");
|
|
8
|
+
console.info(`Loaded keys from ".env" file.`);
|
|
9
|
+
}
|
|
10
|
+
catch { }
|
|
11
|
+
const agent = process.env.XMTP_WALLET_KEY
|
|
12
|
+
? await Agent.create()
|
|
13
|
+
: await Agent.create(createSigner(createUser()), {
|
|
14
|
+
dbPath: null,
|
|
15
|
+
});
|
|
16
|
+
const router = new CommandRouter();
|
|
17
|
+
router.command("/version", async (ctx) => {
|
|
18
|
+
await ctx.conversation.send(`v${process.env.npm_package_version}`);
|
|
10
19
|
});
|
|
11
|
-
agent.
|
|
12
|
-
void ctx.conversation.send("First message!");
|
|
13
|
-
});
|
|
14
|
-
agent.on("message", withFilter(f.and(f.notFromSelf, f.textOnly), (ctx) => {
|
|
15
|
-
void ctx.conversation.send("Goodbye!");
|
|
16
|
-
agent.stop();
|
|
17
|
-
}));
|
|
20
|
+
agent.use(router.middleware());
|
|
18
21
|
agent.on("message", (ctx) => {
|
|
19
22
|
console.log("Got message:", ctx.message.content);
|
|
20
23
|
});
|
|
24
|
+
agent.on("message", withFilter(f.startsWith("@agent"), async (ctx) => {
|
|
25
|
+
await ctx.conversation.send("How can I help you?");
|
|
26
|
+
}));
|
|
21
27
|
const errorHandler = (error) => {
|
|
22
28
|
console.log("Caught error", error);
|
|
23
29
|
};
|
|
24
30
|
agent.on("error", errorHandler);
|
|
25
31
|
agent.off("error", errorHandler);
|
|
26
32
|
agent.on("start", () => {
|
|
27
|
-
|
|
28
|
-
const env = agent.client.options?.env;
|
|
29
|
-
const url = `http://xmtp.chat/dm/${address}?env=${env}`;
|
|
30
|
-
console.log(`We are online: ${url}`);
|
|
33
|
+
console.log(`We are online: ${getTestUrl(agent)}`);
|
|
31
34
|
});
|
|
32
35
|
void agent.start();
|
|
33
36
|
//# sourceMappingURL=demo.js.map
|
package/dist/demo.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"demo.js","sourceRoot":"","sources":["../src/demo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3E,IAAI,CAAC;IACH,WAAW,CAAC,MAAM,CAAC,CAAC;IACpB,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;AAChD,CAAC;AAAC,MAAM,CAAC,CAAA,CAAC;AAEV,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe;IACvC,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE;IACtB,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC,EAAE;QAC7C,MAAM,EAAE,IAAI;KACb,CAAC,CAAC;AAEP,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;AAEnC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IACvC,MAAM,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC;AACrE,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;AAE/B,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE;IAC1B,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,KAAK,CAAC,EAAE,CACN,SAAS,EACT,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/C,MAAM,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;AACrD,CAAC,CAAC,CACH,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAAc,EAAE,EAAE;IACtC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAEhC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;AAEjC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,OAAO,CAAC,GAAG,CAAC,kBAAkB,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type AgentEventHandler, type AgentMiddleware } from "../core/Agent.js";
|
|
2
|
+
import type { AgentContext } from "../core/AgentContext.js";
|
|
3
|
+
export declare class CommandRouter<ContentTypes> {
|
|
4
|
+
private commandMap;
|
|
5
|
+
private defaultHandler;
|
|
6
|
+
command(command: string, handler: AgentEventHandler): this;
|
|
7
|
+
default(handler: AgentEventHandler): this;
|
|
8
|
+
handle(ctx: AgentContext): Promise<boolean>;
|
|
9
|
+
middleware: () => AgentMiddleware<ContentTypes>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isText } from "../utils/message.js";
|
|
2
|
+
export class CommandRouter {
|
|
3
|
+
commandMap = new Map();
|
|
4
|
+
defaultHandler = null;
|
|
5
|
+
command(command, handler) {
|
|
6
|
+
if (!command.startsWith("/")) {
|
|
7
|
+
throw new Error('Command must start with "/"');
|
|
8
|
+
}
|
|
9
|
+
this.commandMap.set(command.toLowerCase(), handler);
|
|
10
|
+
return this;
|
|
11
|
+
}
|
|
12
|
+
default(handler) {
|
|
13
|
+
this.defaultHandler = handler;
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
async handle(ctx) {
|
|
17
|
+
if (!isText(ctx.message)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const messageText = ctx.message.content;
|
|
21
|
+
const parts = messageText.split(" ");
|
|
22
|
+
const command = parts[0].toLowerCase();
|
|
23
|
+
// Check if this is a command message
|
|
24
|
+
if (command.startsWith("/")) {
|
|
25
|
+
const handler = this.commandMap.get(command);
|
|
26
|
+
if (handler) {
|
|
27
|
+
await handler(ctx);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// If no command matched and there's a default handler, use it
|
|
32
|
+
if (this.defaultHandler) {
|
|
33
|
+
await this.defaultHandler(ctx);
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
middleware = () => async (ctx, next) => {
|
|
39
|
+
const handled = await this.handle(ctx);
|
|
40
|
+
if (!handled) {
|
|
41
|
+
await next();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=CommandRouter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommandRouter.js","sourceRoot":"","sources":["../../src/middleware/CommandRouter.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,OAAO,aAAa;IAChB,UAAU,GAAG,IAAI,GAAG,EAA6B,CAAC;IAClD,cAAc,GAA6B,IAAI,CAAC;IAExD,OAAO,CAAC,OAAe,EAAE,OAA0B;QACjD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,OAA0B;QAChC,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC;QAC9B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAiB;QAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;QACxC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAEvC,qCAAqC;QACrC,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;gBACnB,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,8DAA8D;QAC9D,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU,GAAwC,GAAG,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC1E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,EAAE,CAAC;QACf,CAAC;IACH,CAAC,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./CommandRouter.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/middleware/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a hex string to a Uint8Array encryption key.
|
|
3
|
+
* @param hex - The hex string
|
|
4
|
+
* @returns The encryption key
|
|
5
|
+
*/
|
|
6
|
+
export declare const getEncryptionKeyFromHex: (hex: string) => Uint8Array;
|
|
7
|
+
/**
|
|
8
|
+
* Generates a complete set of client keys required for XMTP agent initialization.
|
|
9
|
+
*
|
|
10
|
+
* Creates both a wallet private key for client authentication and a database
|
|
11
|
+
* encryption key for secure local storage. The returned keys can be used
|
|
12
|
+
* directly as environment variables.
|
|
13
|
+
*
|
|
14
|
+
* @returns An object containing the keys
|
|
15
|
+
*/
|
|
16
|
+
export declare const generateClientKeys: () => {
|
|
17
|
+
XMTP_DB_ENCRYPTION_KEY: string;
|
|
18
|
+
XMTP_WALLET_KEY: `0x${string}`;
|
|
19
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getRandomValues } from "node:crypto";
|
|
2
|
+
import { secp256k1 } from "@noble/curves/secp256k1.js";
|
|
3
|
+
import { fromString, toString } from "uint8arrays";
|
|
4
|
+
import { toHex } from "viem";
|
|
5
|
+
/**
|
|
6
|
+
* Convert a hex string to a Uint8Array encryption key.
|
|
7
|
+
* @param hex - The hex string
|
|
8
|
+
* @returns The encryption key
|
|
9
|
+
*/
|
|
10
|
+
export const getEncryptionKeyFromHex = (hex) => {
|
|
11
|
+
return fromString(hex, "hex");
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Generates a cryptographically secure random private key for wallet operations.
|
|
15
|
+
*
|
|
16
|
+
* Uses the secp256k1 elliptic curve to generate a private key suitable for
|
|
17
|
+
* Ethereum-compatible wallets and XMTP client authentication.
|
|
18
|
+
*
|
|
19
|
+
* @returns A hex-encoded private key string (64 characters, prefixed with '0x')
|
|
20
|
+
*/
|
|
21
|
+
function generatePrivateKey() {
|
|
22
|
+
return toHex(secp256k1.utils.randomSecretKey());
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generates a cryptographically secure random encryption key for database encryption.
|
|
26
|
+
*
|
|
27
|
+
* Creates a 256-bit (32-byte) encryption key using the Node.js crypto module's
|
|
28
|
+
* secure random number generator.
|
|
29
|
+
*
|
|
30
|
+
* @returns A hex-encoded encryption key string (64 characters)
|
|
31
|
+
*/
|
|
32
|
+
const generateEncryptionKeyHex = () => {
|
|
33
|
+
/* Generate a random encryption key */
|
|
34
|
+
const uint8Array = getRandomValues(new Uint8Array(32));
|
|
35
|
+
/* Convert the encryption key to a hex string */
|
|
36
|
+
return toString(uint8Array, "hex");
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Generates a complete set of client keys required for XMTP agent initialization.
|
|
40
|
+
*
|
|
41
|
+
* Creates both a wallet private key for client authentication and a database
|
|
42
|
+
* encryption key for secure local storage. The returned keys can be used
|
|
43
|
+
* directly as environment variables.
|
|
44
|
+
*
|
|
45
|
+
* @returns An object containing the keys
|
|
46
|
+
*/
|
|
47
|
+
export const generateClientKeys = () => {
|
|
48
|
+
const walletKey = generatePrivateKey();
|
|
49
|
+
const dbEncryptionKey = generateEncryptionKeyHex();
|
|
50
|
+
return {
|
|
51
|
+
XMTP_DB_ENCRYPTION_KEY: dbEncryptionKey,
|
|
52
|
+
XMTP_WALLET_KEY: walletKey,
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAW,EAAc,EAAE;IACjE,OAAO,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAChC,CAAC,CAAC;AAEF;;;;;;;GAOG;AACH,SAAS,kBAAkB;IACzB,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC;AAClD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,wBAAwB,GAAG,GAAG,EAAE;IACpC,sCAAsC;IACtC,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IACvD,gDAAgD;IAChD,OAAO,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;AACrC,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,EAAE;IACrC,MAAM,SAAS,GAAG,kBAAkB,EAAE,CAAC;IACvC,MAAM,eAAe,GAAG,wBAAwB,EAAE,CAAC;IACnD,OAAO;QACL,sBAAsB,EAAE,eAAe;QACvC,eAAe,EAAE,SAAS;KAC3B,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Client } from "@xmtp/node-sdk";
|
|
2
|
+
import type { Agent } from "../core/Agent.js";
|
|
3
|
+
export declare const logDetails: <ContentTypes>(client: Client<ContentTypes>) => Promise<void>;
|
|
4
|
+
/**
|
|
5
|
+
* Returns a URL to test your agent on https://xmtp.chat/ (for development purposes only).
|
|
6
|
+
*
|
|
7
|
+
* @param agent - Your agent instance
|
|
8
|
+
* @returns The URL to test your agent with
|
|
9
|
+
*/
|
|
10
|
+
export declare const getTestUrl: <ContentTypes>(agent: Agent<ContentTypes>) => string;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Client } from "@xmtp/node-sdk";
|
|
2
|
+
export const logDetails = async (client) => {
|
|
3
|
+
const xmtp = `\x1b[38;2;252;76;52m
|
|
4
|
+
██╗ ██╗███╗ ███╗████████╗██████╗
|
|
5
|
+
╚██╗██╔╝████╗ ████║╚══██╔══╝██╔══██╗
|
|
6
|
+
╚███╔╝ ██╔████╔██║ ██║ ██████╔╝
|
|
7
|
+
██╔██╗ ██║╚██╔╝██║ ██║ ██╔═══╝
|
|
8
|
+
██╔╝ ██╗██║ ╚═╝ ██║ ██║ ██║
|
|
9
|
+
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝
|
|
10
|
+
\x1b[0m`;
|
|
11
|
+
const clientsByAddress = client.accountIdentifier?.identifier;
|
|
12
|
+
const inboxId = client.inboxId;
|
|
13
|
+
const installationId = client.installationId;
|
|
14
|
+
const environments = client.options?.env ?? "dev";
|
|
15
|
+
const urls = [`http://xmtp.chat/dm/${clientsByAddress}`];
|
|
16
|
+
const conversations = await client.conversations.list();
|
|
17
|
+
const inboxState = await client.preferences.inboxState();
|
|
18
|
+
const keyPackageStatuses = await client.getKeyPackageStatusesForInstallationIds([installationId]);
|
|
19
|
+
let createdDate = new Date();
|
|
20
|
+
let expiryDate = new Date();
|
|
21
|
+
// Extract key package status for the specific installation
|
|
22
|
+
const keyPackageStatus = keyPackageStatuses[installationId] ?? {};
|
|
23
|
+
if (keyPackageStatus.lifetime) {
|
|
24
|
+
createdDate = new Date(Number(keyPackageStatus.lifetime.notBefore) * 1000);
|
|
25
|
+
expiryDate = new Date(Number(keyPackageStatus.lifetime.notAfter) * 1000);
|
|
26
|
+
}
|
|
27
|
+
console.log(`
|
|
28
|
+
${xmtp}
|
|
29
|
+
|
|
30
|
+
✓ XMTP Client:
|
|
31
|
+
• InboxId: ${inboxId}
|
|
32
|
+
• Version: ${Client.version}
|
|
33
|
+
• Address: ${clientsByAddress}
|
|
34
|
+
• Conversations: ${conversations.length}
|
|
35
|
+
• Installations: ${inboxState.installations.length}
|
|
36
|
+
• InstallationId: ${installationId}
|
|
37
|
+
• Key Package created: ${createdDate.toLocaleString()}
|
|
38
|
+
• Key Package valid until: ${expiryDate.toLocaleString()}
|
|
39
|
+
• Networks: ${environments}
|
|
40
|
+
${urls.map((url) => `• URL: ${url}`).join("\n")}`);
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Returns a URL to test your agent on https://xmtp.chat/ (for development purposes only).
|
|
44
|
+
*
|
|
45
|
+
* @param agent - Your agent instance
|
|
46
|
+
* @returns The URL to test your agent with
|
|
47
|
+
*/
|
|
48
|
+
export const getTestUrl = (agent) => {
|
|
49
|
+
const address = agent.client.accountIdentifier?.identifier;
|
|
50
|
+
const env = agent.client.options?.env ?? "dev";
|
|
51
|
+
return `http://xmtp.chat/dm/${address}?env=${env}`;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/utils/debug.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,MAA4B,EAC5B,EAAE;IACF,MAAM,IAAI,GAAG;;;;;;;UAOL,CAAC;IAET,MAAM,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,EAAE,UAAU,CAAC;IAC9D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IAC/B,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IAC7C,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC;IAElD,MAAM,IAAI,GAAG,CAAC,uBAAuB,gBAAgB,EAAE,CAAC,CAAC;IAEzD,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,CAAC;IACzD,MAAM,kBAAkB,GACtB,MAAM,MAAM,CAAC,uCAAuC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;IAEzE,IAAI,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7B,IAAI,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC;IAE5B,2DAA2D;IAC3D,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAClE,IAAI,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QAC9B,WAAW,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3E,UAAU,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;IAC3E,CAAC;IACD,OAAO,CAAC,GAAG,CAAC;MACR,IAAI;;;iBAGO,OAAO;iBACP,MAAM,CAAC,OAAO;iBACd,gBAAgB;uBACV,aAAa,CAAC,MAAM;uBACpB,UAAU,CAAC,aAAa,CAAC,MAAM;wBAC9B,cAAc;6BACT,WAAW,CAAC,cAAc,EAAE;iCACxB,UAAU,CAAC,cAAc,EAAE;kBAC1C,YAAY;MACxB,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAe,KAA0B,EAAE,EAAE;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,iBAAiB,EAAE,UAAU,CAAC;IAC3D,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC;IAC/C,OAAO,uBAAuB,OAAO,QAAQ,GAAG,EAAE,CAAC;AACrD,CAAC,CAAC"}
|
package/dist/utils/filter.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Client, DecodedMessage } from "@xmtp/node-sdk";
|
|
2
|
-
import type { AgentContext } from "
|
|
2
|
+
import type { AgentContext } from "../core/AgentContext.js";
|
|
3
3
|
/**
|
|
4
4
|
* Function type for filtering messages based on content and client state.
|
|
5
5
|
*/
|
|
@@ -11,6 +11,13 @@ export type MessageFilter<ContentTypes> = (message: DecodedMessage, client: Clie
|
|
|
11
11
|
* @returns Filter function
|
|
12
12
|
*/
|
|
13
13
|
declare function fromSender<ContentTypes>(senderInboxId: string | string[]): MessageFilter<ContentTypes>;
|
|
14
|
+
/**
|
|
15
|
+
* Creates a filter that matches text messages starting with a specific string.
|
|
16
|
+
*
|
|
17
|
+
* @param prefix - The string prefix to match against
|
|
18
|
+
* @returns Filter function
|
|
19
|
+
*/
|
|
20
|
+
declare function startsWith<ContentTypes>(prefix: string): MessageFilter<ContentTypes>;
|
|
14
21
|
/**
|
|
15
22
|
* Creates a filter that requires all provided filters to pass
|
|
16
23
|
*
|
|
@@ -40,6 +47,17 @@ export declare const filter: {
|
|
|
40
47
|
fromSelf: MessageFilter<unknown>;
|
|
41
48
|
textOnly: MessageFilter<unknown>;
|
|
42
49
|
fromSender: typeof fromSender;
|
|
50
|
+
startsWith: typeof startsWith;
|
|
51
|
+
and: typeof and;
|
|
52
|
+
or: typeof or;
|
|
53
|
+
not: typeof not;
|
|
54
|
+
};
|
|
55
|
+
export declare const f: {
|
|
56
|
+
notFromSelf: MessageFilter<unknown>;
|
|
57
|
+
fromSelf: MessageFilter<unknown>;
|
|
58
|
+
textOnly: MessageFilter<unknown>;
|
|
59
|
+
fromSender: typeof fromSender;
|
|
60
|
+
startsWith: typeof startsWith;
|
|
43
61
|
and: typeof and;
|
|
44
62
|
or: typeof or;
|
|
45
63
|
not: typeof not;
|
package/dist/utils/filter.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ContentTypeText } from "@xmtp/content-type-text";
|
|
2
|
+
import { getTextContent } from "./message.js";
|
|
2
3
|
/**
|
|
3
4
|
* Creates a filter that excludes messages from the agent itself.
|
|
4
5
|
*
|
|
@@ -43,6 +44,18 @@ function fromSender(senderInboxId) {
|
|
|
43
44
|
return senderIds.includes(message.senderInboxId);
|
|
44
45
|
};
|
|
45
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates a filter that matches text messages starting with a specific string.
|
|
49
|
+
*
|
|
50
|
+
* @param prefix - The string prefix to match against
|
|
51
|
+
* @returns Filter function
|
|
52
|
+
*/
|
|
53
|
+
function startsWith(prefix) {
|
|
54
|
+
return (message) => {
|
|
55
|
+
const text = getTextContent(message);
|
|
56
|
+
return !!(text && text.startsWith(prefix));
|
|
57
|
+
};
|
|
58
|
+
}
|
|
46
59
|
/**
|
|
47
60
|
* Creates a filter that requires all provided filters to pass
|
|
48
61
|
*
|
|
@@ -96,11 +109,13 @@ export const filter = {
|
|
|
96
109
|
textOnly: textOnly(),
|
|
97
110
|
// factory functions
|
|
98
111
|
fromSender,
|
|
112
|
+
startsWith,
|
|
99
113
|
// combinators
|
|
100
114
|
and,
|
|
101
115
|
or,
|
|
102
116
|
not,
|
|
103
117
|
};
|
|
118
|
+
export const f = filter;
|
|
104
119
|
export const withFilter = (filter, listener) => (ctx) => {
|
|
105
120
|
if (filter(ctx.message, ctx.client)) {
|
|
106
121
|
listener(ctx);
|
package/dist/utils/filter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/utils/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/utils/filter.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Reaction } from "@xmtp/content-type-reaction";
|
|
2
|
+
import { type RemoteAttachment } from "@xmtp/content-type-remote-attachment";
|
|
3
|
+
import { type Reply } from "@xmtp/content-type-reply";
|
|
4
|
+
import type { DecodedMessage } from "@xmtp/node-sdk";
|
|
5
|
+
type ContentMessage = Pick<DecodedMessage, "content" | "contentType" | "fallback">;
|
|
6
|
+
export declare const isReaction: <M extends ContentMessage>(m: M) => m is M & {
|
|
7
|
+
content: Reaction;
|
|
8
|
+
};
|
|
9
|
+
export declare const isReply: <M extends ContentMessage>(m: M) => m is M & {
|
|
10
|
+
content: Reply;
|
|
11
|
+
};
|
|
12
|
+
export declare const isTextReply: <M extends ContentMessage>(m: M) => m is M & {
|
|
13
|
+
content: Reply & {
|
|
14
|
+
content: string;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare const isText: <M extends ContentMessage>(m: M) => m is M & {
|
|
18
|
+
content: string;
|
|
19
|
+
};
|
|
20
|
+
export declare const isRemoteAttachment: <M extends ContentMessage>(m: M) => m is M & {
|
|
21
|
+
content: RemoteAttachment;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Extracts the text content from various XMTP message types.
|
|
25
|
+
*
|
|
26
|
+
* Supports extracting text from:
|
|
27
|
+
* - Text messages: Returns the direct string content
|
|
28
|
+
* - Text replies: Returns the reply content text
|
|
29
|
+
* - Reactions: Returns the reaction content (emoji/text)
|
|
30
|
+
*
|
|
31
|
+
* @param message - The decoded message to extract text from
|
|
32
|
+
* @returns The text content as a string, or `undefined` for message types that don't contain extractable text content
|
|
33
|
+
*/
|
|
34
|
+
export declare const getTextContent: (message: ContentMessage) => string | undefined;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ContentTypeReaction, } from "@xmtp/content-type-reaction";
|
|
2
|
+
import { ContentTypeRemoteAttachment, } from "@xmtp/content-type-remote-attachment";
|
|
3
|
+
import { ContentTypeReply } from "@xmtp/content-type-reply";
|
|
4
|
+
import { ContentTypeText } from "@xmtp/content-type-text";
|
|
5
|
+
export const isReaction = (m) => !!m.contentType?.sameAs(ContentTypeReaction);
|
|
6
|
+
export const isReply = (m) => !!m.contentType?.sameAs(ContentTypeReply);
|
|
7
|
+
export const isTextReply = (m) => isReply(m) && typeof m.content.content === "string";
|
|
8
|
+
export const isText = (m) => !!m.contentType?.sameAs(ContentTypeText);
|
|
9
|
+
export const isRemoteAttachment = (m) => !!m.contentType?.sameAs(ContentTypeRemoteAttachment);
|
|
10
|
+
/**
|
|
11
|
+
* Extracts the text content from various XMTP message types.
|
|
12
|
+
*
|
|
13
|
+
* Supports extracting text from:
|
|
14
|
+
* - Text messages: Returns the direct string content
|
|
15
|
+
* - Text replies: Returns the reply content text
|
|
16
|
+
* - Reactions: Returns the reaction content (emoji/text)
|
|
17
|
+
*
|
|
18
|
+
* @param message - The decoded message to extract text from
|
|
19
|
+
* @returns The text content as a string, or `undefined` for message types that don't contain extractable text content
|
|
20
|
+
*/
|
|
21
|
+
export const getTextContent = (message) => {
|
|
22
|
+
switch (true) {
|
|
23
|
+
case isReaction(message):
|
|
24
|
+
case isTextReply(message):
|
|
25
|
+
return message.content.content;
|
|
26
|
+
case isText(message):
|
|
27
|
+
return message.content;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../../src/utils/message.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAEpB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,2BAA2B,GAE5B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAc,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAQ1D,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,CAAI,EAC4B,EAAE,CAClC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/C,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,CAAI,EACyB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,CAAI,EAC+C,EAAE,CACrD,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC;AAEtD,MAAM,CAAC,MAAM,MAAM,GAAG,CACpB,CAAI,EAC0B,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;AAE5E,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,CAAI,EACoC,EAAE,CAC1C,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,2BAA2B,CAAC,CAAC;AAEvD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAuB,EAAE,EAAE;IACxD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,KAAK,WAAW,CAAC,OAAO,CAAC;YACvB,OAAO,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QACjC,KAAK,MAAM,CAAC,OAAO,CAAC;YAClB,OAAO,OAAO,CAAC,OAAO,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -4,8 +4,13 @@
|
|
|
4
4
|
"url": "https://github.com/xmtp/xmtp-js/issues"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@
|
|
8
|
-
"@xmtp/
|
|
7
|
+
"@noble/curves": "^2.0.0",
|
|
8
|
+
"@xmtp/content-type-reaction": "workspace:^",
|
|
9
|
+
"@xmtp/content-type-remote-attachment": "workspace:^",
|
|
10
|
+
"@xmtp/content-type-reply": "workspace:^",
|
|
11
|
+
"@xmtp/content-type-text": "workspace:^",
|
|
12
|
+
"@xmtp/node-sdk": "workspace:^",
|
|
13
|
+
"uint8arrays": "^5.1.0",
|
|
9
14
|
"viem": "^2.31.7"
|
|
10
15
|
},
|
|
11
16
|
"description": "XMTP Agent SDK for interacting with XMTP networks",
|
|
@@ -13,6 +18,7 @@
|
|
|
13
18
|
"@arethetypeswrong/cli": "^0.18.2",
|
|
14
19
|
"@types/node": "^22.16.3",
|
|
15
20
|
"@vitest/coverage-v8": "^3.2.4",
|
|
21
|
+
"tsc-alias": "^1.8.16",
|
|
16
22
|
"tsx": "^4.20.3",
|
|
17
23
|
"typescript": "^5.8.3",
|
|
18
24
|
"vite": "^7.0.4",
|
|
@@ -53,15 +59,17 @@
|
|
|
53
59
|
"url": "git+https://git@github.com/xmtp/xmtp-js.git"
|
|
54
60
|
},
|
|
55
61
|
"scripts": {
|
|
56
|
-
"build": "yarn clean:dist && tsc -p tsconfig.build.json && attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
62
|
+
"build": "yarn clean:dist && tsc -p tsconfig.build.json && tsc-alias && attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
57
63
|
"clean": "rm -rf .turbo && rm -rf node_modules && yarn clean:dist",
|
|
58
64
|
"clean:dist": "rm -rf dist",
|
|
65
|
+
"demo": "tsx src/demo.ts",
|
|
59
66
|
"dev": "tsx --watch src/main.ts",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
67
|
+
"gen:keys": "tsx src/bin/generateKeys.ts",
|
|
68
|
+
"start": "yarn demo",
|
|
69
|
+
"test": "yarn typecheck && vitest --typecheck",
|
|
62
70
|
"test:cov": "vitest run --coverage",
|
|
63
71
|
"typecheck": "tsc --noEmit"
|
|
64
72
|
},
|
|
65
73
|
"type": "module",
|
|
66
|
-
"version": "0.0.
|
|
74
|
+
"version": "0.0.5"
|
|
67
75
|
}
|