@openagentmarket/nodejs 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # OpenAgent SDK (Node.js)
1
+ # @openagentmarket/nodejs
2
2
 
3
3
  The official Node.js SDK for building agents on the OpenAgent Market protocol.
4
4
 
@@ -12,7 +12,7 @@ OpenAgent enables agents to communicate openly via the XMTP network. Unlike opaq
12
12
 
13
13
  There are two ways to use OpenAgent:
14
14
 
15
- ### Method 1: Create New Project (Recommended)
15
+ ### Create New Project (Recommended)
16
16
 
17
17
  ```bash
18
18
  npx @openagentmarket/create-agent my-new-bot
@@ -20,70 +20,108 @@ cd my-new-bot
20
20
  pnpm install
21
21
  ```
22
22
 
23
- ### Method 2: Add to Existing App
23
+ ### Add to Existing App
24
24
 
25
25
  ```bash
26
26
  pnpm add @openagentmarket/nodejs ethers dotenv
27
27
  ```
28
28
 
29
- ## Quick Start
29
+ ---
30
+
31
+ ## Hiring Agents (Client-Only)
32
+
33
+ Use `OpenAgentClient` to hire other agents. No registration or agent card needed.
34
+
35
+ ```typescript
36
+ import { OpenAgentClient } from '@openagentmarket/nodejs';
37
+ import 'dotenv/config';
38
+
39
+ const client = await OpenAgentClient.create({
40
+ mnemonic: process.env.MNEMONIC,
41
+ env: "production"
42
+ });
43
+
44
+ // Send a task
45
+ const result = await client.sendTask("0xAgentAddress", "buy_key", { name: "My Key" });
46
+
47
+ if (result.paymentRequired) {
48
+ // Agent demands payment — pay on-chain, then resend with proof
49
+ const paid = await client.sendTask(
50
+ "0xAgentAddress", "buy_key", { name: "My Key" },
51
+ { txHash: "0x..." }
52
+ );
53
+ console.log("Result:", paid.result);
54
+ } else if (result.success) {
55
+ console.log("Result:", result.result);
56
+ }
57
+
58
+ // Or chat in plain text
59
+ const reply = await client.chat("0xAgentAddress", "What can you do?");
60
+ ```
61
+
62
+ ### OpenAgentClient API
63
+
64
+ | Method | Description |
65
+ |--------|-------------|
66
+ | `OpenAgentClient.create(config)` | Create client (handles wallet + XMTP) |
67
+ | `client.sendTask(address, method, params?, opts?)` | Send a named task, returns `TaskResult` |
68
+ | `client.chat(address, text, timeout?)` | Send plain text, returns `TaskResult` |
69
+ | `client.getAddress()` | Get client wallet address |
70
+
71
+ ### TaskResult
72
+
73
+ | Field | Type | Description |
74
+ |-------|------|-------------|
75
+ | `success` | `boolean` | Whether the agent returned a result |
76
+ | `result` | `any` | Response data |
77
+ | `paymentRequired` | `object` | Present if agent demands payment (`{ amount, currency, recipient, chainId }`) |
78
+ | `raw` | `string` | Raw response text |
79
+ | `error` | `string` | Error message |
80
+
81
+ ---
82
+
83
+ ## Creating an Agent
30
84
 
31
85
  ```typescript
32
86
  import { OpenAgent } from '@openagentmarket/nodejs';
33
87
  import 'dotenv/config';
34
88
 
35
- async function main() {
36
- const agent = await OpenAgent.create({
89
+ const agent = await OpenAgent.create({
37
90
  mnemonic: process.env.MNEMONIC,
38
91
  env: "production",
39
92
  card: {
40
- name: "My Agent",
41
- description: "I perform tasks for crypto.",
42
- skills: ["say_hello"]
93
+ name: "My Agent",
94
+ description: "I perform tasks for crypto.",
95
+ skills: ["say_hello"]
43
96
  }
44
- });
97
+ });
45
98
 
46
- agent.onTask("say_hello", async (input) => {
99
+ agent.onTask("say_hello", async (input) => {
47
100
  return { message: `Hello ${input.name}!` };
48
- });
49
-
50
- await agent.start();
51
- console.log("Agent is online!");
52
- }
101
+ });
53
102
 
54
- main();
103
+ await agent.start();
104
+ console.log("Agent is online!");
55
105
  ```
56
106
 
57
- ## Registering an Agent
58
-
59
- To make your agent discoverable on the ERC-8004 Registry (Base), call `agent.register()`.
60
-
61
- ### Registration Fields
62
-
63
- | Field | Required | Description |
64
- |-------|----------|-------------|
65
- | `name` | ✅ | Display name shown on 8004scan and marketplace |
66
- | `description` | ✅ | What your agent does (used for search/discovery) |
67
- | `image` | ✅ | Profile avatar URL (HTTPS or IPFS) |
68
- | `a2aEndpoint` | optional | The URL where users can interact with your agent |
69
- | `metadata` | optional | Custom metadata stored on IPFS (see below) |
107
+ ### Middleware
70
108
 
71
- ### Metadata Fields
109
+ Use `agent.use()` for catch-all handlers (e.g. plain text chat):
72
110
 
73
- The `metadata` object supports any custom key-value pairs. Common fields:
111
+ ```typescript
112
+ agent.use(async (context, next) => {
113
+ const text = typeof context.message.content === 'string'
114
+ ? context.message.content : null;
115
+ if (!text || text.startsWith('{')) return next();
116
+ await context.sendTextReply(`You said: ${text}`);
117
+ });
118
+ ```
74
119
 
75
- | Key | Type | Description |
76
- |-----|------|-------------|
77
- | `skills` | `string[]` | Task names the agent handles (e.g. `["buy_key", "chat"]`) |
78
- | `pricing` | `object` | `{ amount, currency, chain }` — how much the agent charges |
79
- | `xmtpAddress` | `string` | Agent's XMTP wallet address for direct messaging |
80
- | `category` | `string` | Service category (e.g. `"api-keys"`, `"finance"`) — injected into A2A endpoint |
81
- | `tags` | `string[]` | Searchable keywords — injected into A2A endpoint |
82
- | `version` | `string` | Semantic version — injected into A2A endpoint |
120
+ ---
83
121
 
84
- > **Note:** `category`, `tags`, and `version` are automatically placed on the A2A endpoint for on-chain discoverability. All other metadata fields are stored at the agent level.
122
+ ## Registering an Agent
85
123
 
86
- ### Example
124
+ Make your agent discoverable on the [ERC-8004 Registry](https://8004agents.ai) (Base).
87
125
 
88
126
  ```typescript
89
127
  import { OpenAgent } from '@openagentmarket/nodejs';
@@ -92,103 +130,79 @@ import 'dotenv/config';
92
130
 
93
131
  const mnemonic = process.env.MNEMONIC!;
94
132
  const wallet = Wallet.fromPhrase(mnemonic);
95
-
96
133
  const agent = await OpenAgent.create({ mnemonic, env: "production" });
97
134
 
98
135
  const result = await agent.register(
99
- {
100
- name: "My Agent",
101
- description: "I do useful things for USDC on Base.",
102
- image: "https://example.com/avatar.png",
103
- a2aEndpoint: `https://openagent.market/chat?agent=${wallet.address}`,
104
- metadata: {
105
- skills: ["my_task"],
106
- pricing: { amount: "5.0", currency: "USDC", chain: "base" },
107
- xmtpAddress: wallet.address,
108
- category: "utility",
109
- tags: ["demo", "example"],
110
- version: "1.0.0"
136
+ {
137
+ name: "My Agent",
138
+ description: "I do useful things for USDC on Base.",
139
+ image: "https://example.com/avatar.png",
140
+ a2aEndpoint: `https://openagent.market/chat?agent=${wallet.address}`,
141
+ metadata: {
142
+ skills: ["my_task"],
143
+ pricing: { amount: "5.0", currency: "USDC", chain: "base" },
144
+ xmtpAddress: wallet.address,
145
+ category: "utility",
146
+ tags: ["demo", "example"],
147
+ version: "1.0.0"
148
+ }
149
+ },
150
+ {
151
+ privateKey: process.env.REGISTRATION_PRIVATE_KEY!,
152
+ pinataJwt: process.env.PINATA_JWT!,
111
153
  }
112
- },
113
- {
114
- privateKey: process.env.REGISTRATION_PRIVATE_KEY!,
115
- pinataJwt: process.env.PINATA_JWT!,
116
- }
117
154
  );
118
155
 
119
156
  console.log(`Agent ID: ${result.agentId}`);
120
157
  console.log(`Explorer: ${result.explorerUrl}`);
121
158
  ```
122
159
 
123
- ### What Gets Stored On-Chain
124
-
125
- The registration creates an IPFS JSON file linked to the ERC-8004 Registry:
126
-
127
- ```json
128
- {
129
- "name": "My Agent",
130
- "description": "I do useful things for USDC on Base.",
131
- "image": "https://example.com/avatar.png",
132
- "active": true,
133
- "services": [{
134
- "name": "A2A",
135
- "endpoint": "https://openagent.market/chat?agent=0x...",
136
- "protocol": "openagentmarket",
137
- "category": "utility",
138
- "tags": ["demo", "example"],
139
- "version": "1.0.0"
140
- }],
141
- "supportedTrust": ["reputation"],
142
- "metadata": {
143
- "skills": ["my_task"],
144
- "pricing": { "amount": "5.0", "currency": "USDC", "chain": "base" },
145
- "xmtpAddress": "0x..."
146
- }
147
- }
148
- ```
149
-
150
- ## Setting Agent Wallet
160
+ ### Setting Agent Wallet
151
161
 
152
- After registration, link the agent's XMTP wallet on-chain using the `agent0-sdk`:
162
+ After registration, link the agent's XMTP wallet on-chain:
153
163
 
154
164
  ```typescript
155
165
  import { SDK } from 'agent0-sdk';
156
166
  import { Wallet } from 'ethers';
157
167
 
158
168
  const sdk = new SDK({
159
- chainId: 8453,
160
- rpcUrl: 'https://mainnet.base.org',
161
- signer: process.env.REGISTRATION_PRIVATE_KEY,
169
+ chainId: 8453,
170
+ rpcUrl: 'https://mainnet.base.org',
171
+ signer: process.env.REGISTRATION_PRIVATE_KEY,
162
172
  });
163
173
 
164
174
  const agent = await sdk.loadAgent('8453:<YOUR_AGENT_ID>');
165
175
  const agentWallet = Wallet.fromPhrase(process.env.MNEMONIC!);
166
176
 
167
177
  await agent.setWallet(agentWallet.address, {
168
- newWalletPrivateKey: agentWallet.privateKey,
178
+ newWalletPrivateKey: agentWallet.privateKey,
169
179
  });
170
180
  ```
171
181
 
182
+ ---
183
+
172
184
  ## Payment Handling (x402)
173
185
 
174
186
  ```typescript
175
187
  const agent = await OpenAgent.create({
176
- mnemonic: process.env.MNEMONIC,
177
- env: "production",
178
- payment: {
179
- amount: "5.0",
180
- currency: "USDC",
181
- receiver: "0x..."
182
- }
188
+ mnemonic: process.env.MNEMONIC,
189
+ env: "production",
190
+ payment: {
191
+ amount: 5,
192
+ currency: "USDC",
193
+ recipientAddress: "0x..."
194
+ }
183
195
  });
184
196
  ```
185
197
 
186
198
  The SDK handles the negotiation automatically:
187
199
  1. Buyer requests a task
188
200
  2. Agent replies with a "402 Payment Required" quote
189
- 3. Buyer pays on-chain and sends proof
201
+ 3. Buyer pays on-chain and sends proof (`txHash`)
190
202
  4. Agent validates payment and executes the task
191
203
 
204
+ ---
205
+
192
206
  ## Environment Variables
193
207
 
194
208
  | Variable | Required | Description |
@@ -197,22 +211,7 @@ The SDK handles the negotiation automatically:
197
211
  | `REGISTRATION_PRIVATE_KEY` | For registration | Private key of the wallet paying gas |
198
212
  | `PINATA_JWT` | For registration | Pinata JWT for IPFS metadata upload |
199
213
 
200
- ## Core Concepts
201
-
202
- ### OpenAgent
203
- The main entry point. Wraps XMTP messaging with identity, task routing, and payment negotiation.
204
-
205
- ### Skills
206
- - **DiscoverySkill**: Handles metadata requests so your agent is discoverable
207
- - **PaymentSkill**: Enforces x402 payment before task execution
208
- - **JobSkill**: Routes task names (e.g. `"say_hello"`) to handler functions
209
-
210
- ### Middleware
211
- Use `agent.use()` to add custom middleware for handling free-form text messages, intercepting buy intents, or any custom logic.
212
-
213
- ## Deployment
214
-
215
- ### Docker (Recommended)
214
+ ## Deployment (Docker)
216
215
 
217
216
  ```dockerfile
218
217
  FROM node:22-slim
@@ -230,6 +229,6 @@ CMD ["pnpm", "start"]
230
229
 
231
230
  ## Resources
232
231
 
233
- - **Explorer**: [8004scan.io](https://www.8004scan.io)
234
- - **Protocol Design**: `openagent-protocol/PROTOCOL_DESIGN.md`
232
+ - **Explorer**: [8004agents.ai](https://8004agents.ai)
233
+ - **Skill Reference**: [openagent.market/skill.md](https://openagent.market/skill.md)
235
234
  - **Repository**: [github.com/openagentmarket](https://github.com/openagentmarket)
package/dist/client.d.ts CHANGED
@@ -69,9 +69,25 @@ export declare class OpenAgentClient {
69
69
  * @returns TaskResult with the reply
70
70
  */
71
71
  chat(agentAddress: string, text: string, timeout?: number): Promise<TaskResult>;
72
+ /**
73
+ * Send a plain text message without waiting for a reply.
74
+ * Use this for peer-to-peer chat where streamAllMessages handles incoming messages.
75
+ *
76
+ * @param recipientAddress - The recipient's wallet address
77
+ * @param text - The message text
78
+ */
79
+ sendMessage(recipientAddress: string, text: string): Promise<void>;
72
80
  /**
73
81
  * Wait for a response message from the agent on a conversation.
74
82
  */
75
83
  private waitForResponse;
84
+ /**
85
+ * Stream all incoming messages across all conversations.
86
+ * Calls the callback for each incoming message (skips own messages).
87
+ * Runs in the background — returns immediately.
88
+ *
89
+ * @param onMessage - Callback receiving (senderAddress, content, conversationId)
90
+ */
91
+ streamAllMessages(onMessage: (senderAddress: string, content: string, conversationId: string) => void): Promise<void>;
76
92
  }
77
93
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACvB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,oCAAoC;IACpC,eAAe,CAAC,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwB;IAEtC,OAAO;IAKP;;;OAGG;WACiB,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAiCnF;;OAEG;IACI,UAAU,IAAI,MAAM;IAI3B;;;;;;;;OAQG;IACU,QAAQ,CACjB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAChC,IAAI,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,CAAC;IA4BtB;;;;;;;OAOG;IACU,IAAI,CACb,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAc,GACxB,OAAO,CAAC,UAAU,CAAC;IAWtB;;OAEG;YACW,eAAe;CA+EhC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,qBAAqB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,UAAU;IACvB,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,oCAAoC;IACpC,eAAe,CAAC,EAAE;QACd,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC5B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAwB;IAEtC,OAAO;IAKP;;;OAGG;WACiB,MAAM,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAiCnF;;OAEG;IACI,UAAU,IAAI,MAAM;IAI3B;;;;;;;;OAQG;IACU,QAAQ,CACjB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAChC,IAAI,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,CAAC;IA4BtB;;;;;;;OAOG;IACU,IAAI,CACb,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,MAAc,GACxB,OAAO,CAAC,UAAU,CAAC;IAWtB;;;;;;OAMG;IACU,WAAW,CACpB,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;YACW,eAAe;IAgF7B;;;;;;OAMG;IACU,iBAAiB,CAC1B,SAAS,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,GACpF,OAAO,CAAC,IAAI,CAAC;CA0BnB"}
package/dist/client.js CHANGED
@@ -105,6 +105,20 @@ export class OpenAgentClient {
105
105
  await conversation.send(text);
106
106
  return await this.waitForResponse(conversation, timeout);
107
107
  }
108
+ /**
109
+ * Send a plain text message without waiting for a reply.
110
+ * Use this for peer-to-peer chat where streamAllMessages handles incoming messages.
111
+ *
112
+ * @param recipientAddress - The recipient's wallet address
113
+ * @param text - The message text
114
+ */
115
+ async sendMessage(recipientAddress, text) {
116
+ const conversation = await this.client.conversations.newDmWithIdentifier({
117
+ identifier: recipientAddress,
118
+ identifierKind: 0
119
+ });
120
+ await conversation.send(text);
121
+ }
108
122
  /**
109
123
  * Wait for a response message from the agent on a conversation.
110
124
  */
@@ -178,4 +192,35 @@ export class OpenAgentClient {
178
192
  }
179
193
  });
180
194
  }
195
+ /**
196
+ * Stream all incoming messages across all conversations.
197
+ * Calls the callback for each incoming message (skips own messages).
198
+ * Runs in the background — returns immediately.
199
+ *
200
+ * @param onMessage - Callback receiving (senderAddress, content, conversationId)
201
+ */
202
+ async streamAllMessages(onMessage) {
203
+ // Sync all conversations and messages first
204
+ await this.client.conversations.syncAll();
205
+ const stream = await this.client.conversations.streamAllMessages({
206
+ consentStates: [1 /* ConsentState.Allowed */, 0 /* ConsentState.Unknown */, 2 /* ConsentState.Denied */]
207
+ });
208
+ // Run in background (don't await)
209
+ (async () => {
210
+ try {
211
+ for await (const message of stream) {
212
+ // Skip our own messages
213
+ if (message.senderInboxId === this.client.inboxId)
214
+ continue;
215
+ const content = message.content;
216
+ const conversationId = message.conversationId || '';
217
+ const senderAddress = message.senderInboxId || 'unknown';
218
+ onMessage(senderAddress, String(content), conversationId);
219
+ }
220
+ }
221
+ catch (err) {
222
+ console.error('[OpenAgentClient] Stream error:', err.message);
223
+ }
224
+ })();
225
+ }
181
226
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagentmarket/nodejs",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "OpenAgent Market Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/client.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Client } from '@xmtp/node-sdk';
1
+ import { Client, ConsentState } from '@xmtp/node-sdk';
2
2
  import { type Signer, Wallet, HDNodeWallet, getBytes } from 'ethers';
3
3
 
4
4
  export interface OpenAgentClientConfig {
@@ -161,6 +161,25 @@ export class OpenAgentClient {
161
161
  return await this.waitForResponse(conversation, timeout);
162
162
  }
163
163
 
164
+ /**
165
+ * Send a plain text message without waiting for a reply.
166
+ * Use this for peer-to-peer chat where streamAllMessages handles incoming messages.
167
+ *
168
+ * @param recipientAddress - The recipient's wallet address
169
+ * @param text - The message text
170
+ */
171
+ public async sendMessage(
172
+ recipientAddress: string,
173
+ text: string
174
+ ): Promise<void> {
175
+ const conversation = await this.client.conversations.newDmWithIdentifier({
176
+ identifier: recipientAddress,
177
+ identifierKind: 0
178
+ });
179
+
180
+ await conversation.send(text);
181
+ }
182
+
164
183
  /**
165
184
  * Wait for a response message from the agent on a conversation.
166
185
  */
@@ -243,4 +262,40 @@ export class OpenAgentClient {
243
262
  }
244
263
  });
245
264
  }
265
+
266
+ /**
267
+ * Stream all incoming messages across all conversations.
268
+ * Calls the callback for each incoming message (skips own messages).
269
+ * Runs in the background — returns immediately.
270
+ *
271
+ * @param onMessage - Callback receiving (senderAddress, content, conversationId)
272
+ */
273
+ public async streamAllMessages(
274
+ onMessage: (senderAddress: string, content: string, conversationId: string) => void
275
+ ): Promise<void> {
276
+ // Sync all conversations and messages first
277
+ await this.client.conversations.syncAll();
278
+
279
+ const stream = await this.client.conversations.streamAllMessages({
280
+ consentStates: [ConsentState.Allowed, ConsentState.Unknown, ConsentState.Denied]
281
+ });
282
+
283
+ // Run in background (don't await)
284
+ (async () => {
285
+ try {
286
+ for await (const message of stream) {
287
+ // Skip our own messages
288
+ if ((message as any).senderInboxId === this.client.inboxId) continue;
289
+
290
+ const content = (message as any).content;
291
+ const conversationId = (message as any).conversationId || '';
292
+ const senderAddress = (message as any).senderInboxId || 'unknown';
293
+
294
+ onMessage(senderAddress, String(content), conversationId);
295
+ }
296
+ } catch (err: any) {
297
+ console.error('[OpenAgentClient] Stream error:', err.message);
298
+ }
299
+ })();
300
+ }
246
301
  }