@xmtp/agent-sdk 0.0.4 → 0.0.6
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 -8
- 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 +46 -8
- 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 +18 -0
- 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 +11 -4
package/README.md
CHANGED
|
@@ -16,11 +16,11 @@ This SDK is based on familiar Node.js patterns: you register event listeners, co
|
|
|
16
16
|
Choose your package manager:
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
npm install @xmtp/agent-sdk
|
|
19
|
+
npm install @xmtp/agent-sdk
|
|
20
20
|
# or
|
|
21
|
-
pnpm add @xmtp/agent-sdk
|
|
21
|
+
pnpm add @xmtp/agent-sdk
|
|
22
22
|
# or
|
|
23
|
-
yarn add @xmtp/agent-sdk
|
|
23
|
+
yarn add @xmtp/agent-sdk
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Quick Start
|
|
@@ -53,6 +53,30 @@ agent.on("start", () => {
|
|
|
53
53
|
await agent.start();
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
+
## Environment Variables
|
|
57
|
+
|
|
58
|
+
The XMTP Agent SDK supports environment variables (`process.env`) to simplify configuration without code changes.
|
|
59
|
+
|
|
60
|
+
**Available Variables:**
|
|
61
|
+
|
|
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:
|
|
71
|
+
|
|
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
|
+
|
|
56
80
|
## Core Concepts
|
|
57
81
|
|
|
58
82
|
### 1. Event‑Driven Architecture
|
|
@@ -80,10 +104,12 @@ Extend your agent with custom business logic using middlewares. Compose cross-cu
|
|
|
80
104
|
**Example:**
|
|
81
105
|
|
|
82
106
|
```ts
|
|
107
|
+
import { CommandRouter } from "@xmtp/agent-sdk";
|
|
108
|
+
|
|
83
109
|
const router = new CommandRouter();
|
|
84
110
|
|
|
85
|
-
router.command("/
|
|
86
|
-
await ctx.conversation.send(
|
|
111
|
+
router.command("/version", async (ctx) => {
|
|
112
|
+
await ctx.conversation.send(`v${process.env.npm_package_version}`);
|
|
87
113
|
});
|
|
88
114
|
|
|
89
115
|
agent.use(router.middleware());
|
|
@@ -98,16 +124,38 @@ Instead of manually checking every incoming message, you can compose simple, reu
|
|
|
98
124
|
```ts
|
|
99
125
|
import { withFilter, filter } from "@xmtp/agent-sdk";
|
|
100
126
|
|
|
101
|
-
|
|
127
|
+
// Using filter in message handler
|
|
128
|
+
agent.on(
|
|
129
|
+
"message",
|
|
130
|
+
withFilter(filter.startsWith("@agent"), async (ctx) => {
|
|
131
|
+
await ctx.conversation.send("How can I help you?");
|
|
132
|
+
}),
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
// Combination of filters
|
|
136
|
+
const combined = filter.and(filter.notFromSelf, filter.textOnly);
|
|
102
137
|
|
|
103
138
|
agent.on(
|
|
104
139
|
"message",
|
|
105
|
-
withFilter(
|
|
140
|
+
withFilter(combined, async (ctx) => {
|
|
106
141
|
await ctx.conversation.send("You sent a text message ✅");
|
|
107
142
|
}),
|
|
108
143
|
);
|
|
109
144
|
```
|
|
110
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
|
+
|
|
111
159
|
### 4. Rich Context
|
|
112
160
|
|
|
113
161
|
Every `message` handler receives an `AgentContext` with:
|
|
@@ -139,7 +187,7 @@ const agent = await Agent.create(signer, {
|
|
|
139
187
|
});
|
|
140
188
|
```
|
|
141
189
|
|
|
142
|
-
##
|
|
190
|
+
## Debugging
|
|
143
191
|
|
|
144
192
|
- [Debug an agent](https://docs.xmtp.org/agents/debug-agents)
|
|
145
193
|
- [Further debugging info](https://docs.xmtp.org/inboxes/debug-your-app#debug-your-inbox-app)
|
|
@@ -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 {
|
|
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";
|
|
3
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
|
@@ -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
|
+
"@noble/curves": "^2.0.0",
|
|
8
|
+
"@xmtp/content-type-reaction": "^2.0.2",
|
|
9
|
+
"@xmtp/content-type-remote-attachment": "^2.0.2",
|
|
7
10
|
"@xmtp/content-type-reply": "^2.0.2",
|
|
8
|
-
"@xmtp/
|
|
11
|
+
"@xmtp/content-type-text": "^2.0.2",
|
|
12
|
+
"@xmtp/node-sdk": "^4.1.0",
|
|
13
|
+
"uint8arrays": "^5.1.0",
|
|
9
14
|
"viem": "^2.31.7"
|
|
10
15
|
},
|
|
11
16
|
"description": "XMTP Agent SDK for interacting with XMTP networks",
|
|
@@ -57,12 +62,14 @@
|
|
|
57
62
|
"build": "yarn clean:dist && tsc -p tsconfig.build.json && tsc-alias && attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
58
63
|
"clean": "rm -rf .turbo && rm -rf node_modules && yarn clean:dist",
|
|
59
64
|
"clean:dist": "rm -rf dist",
|
|
65
|
+
"demo": "tsx src/demo.ts",
|
|
60
66
|
"dev": "tsx --watch src/main.ts",
|
|
61
|
-
"
|
|
62
|
-
"
|
|
67
|
+
"gen:keys": "tsx src/bin/generateKeys.ts",
|
|
68
|
+
"start": "yarn demo",
|
|
69
|
+
"test": "yarn typecheck && vitest --typecheck",
|
|
63
70
|
"test:cov": "vitest run --coverage",
|
|
64
71
|
"typecheck": "tsc --noEmit"
|
|
65
72
|
},
|
|
66
73
|
"type": "module",
|
|
67
|
-
"version": "0.0.
|
|
74
|
+
"version": "0.0.6"
|
|
68
75
|
}
|