@openagentmarket/nodejs 1.1.2 → 1.2.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.
@@ -0,0 +1,77 @@
1
+ export interface OpenAgentClientConfig {
2
+ mnemonic?: string;
3
+ privateKey?: string;
4
+ env?: "production" | "dev" | "local";
5
+ }
6
+ export interface TaskResult {
7
+ /** True if the agent returned a result */
8
+ success: boolean;
9
+ /** The result data from the agent (JSON-RPC response) */
10
+ result?: any;
11
+ /** If the agent demanded payment */
12
+ paymentRequired?: {
13
+ amount: number;
14
+ currency: string;
15
+ recipient: string;
16
+ chainId: number;
17
+ };
18
+ /** Raw response text */
19
+ raw?: string;
20
+ /** Error message if something went wrong */
21
+ error?: string;
22
+ }
23
+ export interface SendTaskOptions {
24
+ /** Timeout in milliseconds (default: 30000) */
25
+ timeout?: number;
26
+ /** Payment proof transaction hash (if prepaying) */
27
+ txHash?: string;
28
+ }
29
+ /**
30
+ * OpenAgentClient — buyer-side SDK for hiring agents via XMTP.
31
+ *
32
+ * No registration or agent card needed. Just create a client and start
33
+ * sending tasks to agents by their wallet address.
34
+ *
35
+ * ```typescript
36
+ * const client = await OpenAgentClient.create({ mnemonic: process.env.MNEMONIC, env: "production" });
37
+ * const result = await client.sendTask("0xAgentAddress", "buy_key", { name: "My Key" });
38
+ * ```
39
+ */
40
+ export declare class OpenAgentClient {
41
+ private client;
42
+ private wallet;
43
+ private constructor();
44
+ /**
45
+ * Create a new OpenAgentClient.
46
+ * Handles wallet creation and XMTP connection.
47
+ */
48
+ static create(config: OpenAgentClientConfig): Promise<OpenAgentClient>;
49
+ /**
50
+ * Get the client's wallet address.
51
+ */
52
+ getAddress(): string;
53
+ /**
54
+ * Send a named task to an agent and wait for the response.
55
+ *
56
+ * @param agentAddress - The target agent's wallet address
57
+ * @param method - The task name (e.g. "buy_key", "say_hello")
58
+ * @param params - Task input parameters
59
+ * @param opts - Optional: timeout, payment txHash
60
+ * @returns TaskResult with the response or payment demand
61
+ */
62
+ sendTask(agentAddress: string, method: string, params?: Record<string, any>, opts?: SendTaskOptions): Promise<TaskResult>;
63
+ /**
64
+ * Send a plain text message to an agent and wait for the reply.
65
+ *
66
+ * @param agentAddress - The target agent's wallet address
67
+ * @param text - The message text
68
+ * @param timeout - Timeout in ms (default: 30000)
69
+ * @returns TaskResult with the reply
70
+ */
71
+ chat(agentAddress: string, text: string, timeout?: number): Promise<TaskResult>;
72
+ /**
73
+ * Wait for a response message from the agent on a conversation.
74
+ */
75
+ private waitForResponse;
76
+ }
77
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +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"}
package/dist/client.js ADDED
@@ -0,0 +1,181 @@
1
+ import { Client } from '@xmtp/node-sdk';
2
+ import { Wallet, getBytes } from 'ethers';
3
+ /**
4
+ * OpenAgentClient — buyer-side SDK for hiring agents via XMTP.
5
+ *
6
+ * No registration or agent card needed. Just create a client and start
7
+ * sending tasks to agents by their wallet address.
8
+ *
9
+ * ```typescript
10
+ * const client = await OpenAgentClient.create({ mnemonic: process.env.MNEMONIC, env: "production" });
11
+ * const result = await client.sendTask("0xAgentAddress", "buy_key", { name: "My Key" });
12
+ * ```
13
+ */
14
+ export class OpenAgentClient {
15
+ client;
16
+ wallet;
17
+ constructor(client, wallet) {
18
+ this.client = client;
19
+ this.wallet = wallet;
20
+ }
21
+ /**
22
+ * Create a new OpenAgentClient.
23
+ * Handles wallet creation and XMTP connection.
24
+ */
25
+ static async create(config) {
26
+ let wallet;
27
+ if (config.mnemonic) {
28
+ wallet = Wallet.fromPhrase(config.mnemonic);
29
+ }
30
+ else if (config.privateKey) {
31
+ wallet = new Wallet(config.privateKey);
32
+ }
33
+ else {
34
+ wallet = Wallet.createRandom();
35
+ }
36
+ // Build XMTP signer adapter
37
+ const signer = {
38
+ getAddress: async () => wallet.address,
39
+ getIdentifier: () => ({
40
+ identifier: wallet.address,
41
+ identifierKind: 0
42
+ }),
43
+ signMessage: async (message) => {
44
+ const sig = await wallet.signMessage(message);
45
+ return getBytes(sig);
46
+ },
47
+ type: "EOA"
48
+ };
49
+ const client = await Client.create(signer, {
50
+ env: config.env || "production"
51
+ });
52
+ console.log(`[OpenAgentClient] Connected as ${wallet.address}`);
53
+ return new OpenAgentClient(client, wallet);
54
+ }
55
+ /**
56
+ * Get the client's wallet address.
57
+ */
58
+ getAddress() {
59
+ return this.wallet.address;
60
+ }
61
+ /**
62
+ * Send a named task to an agent and wait for the response.
63
+ *
64
+ * @param agentAddress - The target agent's wallet address
65
+ * @param method - The task name (e.g. "buy_key", "say_hello")
66
+ * @param params - Task input parameters
67
+ * @param opts - Optional: timeout, payment txHash
68
+ * @returns TaskResult with the response or payment demand
69
+ */
70
+ async sendTask(agentAddress, method, params = {}, opts) {
71
+ const timeout = opts?.timeout ?? 30000;
72
+ // Open DM with the agent
73
+ const conversation = await this.client.conversations.newDmWithIdentifier({
74
+ identifier: agentAddress,
75
+ identifierKind: 0
76
+ });
77
+ // Build JSON-RPC request
78
+ const request = {
79
+ method,
80
+ params,
81
+ id: Date.now()
82
+ };
83
+ // Attach payment proof if provided
84
+ if (opts?.txHash) {
85
+ request.payment = { txHash: opts.txHash };
86
+ }
87
+ // Send as string
88
+ await conversation.send(JSON.stringify(request));
89
+ // Wait for response
90
+ return await this.waitForResponse(conversation, timeout);
91
+ }
92
+ /**
93
+ * Send a plain text message to an agent and wait for the reply.
94
+ *
95
+ * @param agentAddress - The target agent's wallet address
96
+ * @param text - The message text
97
+ * @param timeout - Timeout in ms (default: 30000)
98
+ * @returns TaskResult with the reply
99
+ */
100
+ async chat(agentAddress, text, timeout = 30000) {
101
+ const conversation = await this.client.conversations.newDmWithIdentifier({
102
+ identifier: agentAddress,
103
+ identifierKind: 0
104
+ });
105
+ await conversation.send(text);
106
+ return await this.waitForResponse(conversation, timeout);
107
+ }
108
+ /**
109
+ * Wait for a response message from the agent on a conversation.
110
+ */
111
+ async waitForResponse(conversation, timeout) {
112
+ return new Promise(async (resolve) => {
113
+ const timer = setTimeout(() => {
114
+ resolve({
115
+ success: false,
116
+ error: `Timeout: No response after ${timeout}ms`
117
+ });
118
+ }, timeout);
119
+ try {
120
+ const stream = await conversation.stream();
121
+ for await (const message of stream) {
122
+ // Skip our own messages
123
+ if (message.senderInboxId === this.client.inboxId)
124
+ continue;
125
+ clearTimeout(timer);
126
+ const content = message.content;
127
+ if (typeof content !== 'string') {
128
+ resolve({ success: true, raw: String(content) });
129
+ return;
130
+ }
131
+ // Try to parse as JSON
132
+ try {
133
+ const json = JSON.parse(content);
134
+ // 402 Payment Required
135
+ if (json.type === "PAYMENT_REQUIRED") {
136
+ resolve({
137
+ success: false,
138
+ paymentRequired: json.payment,
139
+ raw: content
140
+ });
141
+ return;
142
+ }
143
+ // JSON-RPC error
144
+ if (json.error) {
145
+ resolve({
146
+ success: false,
147
+ error: json.error.message || JSON.stringify(json.error),
148
+ raw: content
149
+ });
150
+ return;
151
+ }
152
+ // JSON-RPC success
153
+ if (json.result !== undefined) {
154
+ resolve({
155
+ success: true,
156
+ result: json.result,
157
+ raw: content
158
+ });
159
+ return;
160
+ }
161
+ // Generic JSON response
162
+ resolve({ success: true, result: json, raw: content });
163
+ return;
164
+ }
165
+ catch {
166
+ // Plain text response
167
+ resolve({ success: true, result: content, raw: content });
168
+ return;
169
+ }
170
+ }
171
+ }
172
+ catch (err) {
173
+ clearTimeout(timer);
174
+ resolve({
175
+ success: false,
176
+ error: err.message || "Stream error"
177
+ });
178
+ }
179
+ });
180
+ }
181
+ }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './skills/payment.js';
7
7
  export * from './skills/discovery.js';
8
8
  export * from './skills/job.js';
9
9
  export * from './registry.js';
10
+ export * from './client.js';
10
11
  export interface OpenAgentConfig {
11
12
  signer?: Signer;
12
13
  mnemonic?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAY,KAAK,WAAW,IAAI,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvG,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAE9B,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,GAAG,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;CACxC;AAED,qBAAa,SAAS;IAClB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO;WAMa,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC;IAoCvE,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACI,GAAG,CAAC,UAAU,EAAE,eAAe;IAItC;;;;OAIG;IACI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAIrE;;OAEG;IACU,KAAK;IAKlB;;;;OAIG;IACU,QAAQ,CACjB,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,cAAc,CAAC;CAS7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,KAAK,MAAM,EAAoB,MAAM,QAAQ,CAAC;AACvD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvE,OAAO,EAAY,KAAK,WAAW,IAAI,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAEvG,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAE5B,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,GAAG,CAAC,EAAE,YAAY,GAAG,KAAK,GAAG,OAAO,CAAC;CACxC;AAED,qBAAa,SAAS;IAClB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO;WAMa,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC;IAoCvE,OAAO,CAAC,kBAAkB;IAY1B;;OAEG;IACI,GAAG,CAAC,UAAU,EAAE,eAAe;IAItC;;;;OAIG;IACI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC;IAIrE;;OAEG;IACU,KAAK;IAKlB;;;;OAIG;IACU,QAAQ,CACjB,IAAI,EAAE,mBAAmB,EACzB,OAAO,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,cAAc,CAAC;CAS7B"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ export * from './skills/payment.js';
8
8
  export * from './skills/discovery.js';
9
9
  export * from './skills/job.js';
10
10
  export * from './registry.js';
11
+ export * from './client.js';
11
12
  export class OpenAgent {
12
13
  agent;
13
14
  config;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openagentmarket/nodejs",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "description": "OpenAgent Market Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -24,6 +24,7 @@
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
26
  "@xmtp/agent-sdk": "^1.0.0",
27
+ "@xmtp/node-sdk": "^4.6.0",
27
28
  "agent0-sdk": "^1.5.3",
28
29
  "dotenv": "^16.4.0",
29
30
  "ethers": "^6.10.0"
package/src/client.ts ADDED
@@ -0,0 +1,246 @@
1
+ import { Client } from '@xmtp/node-sdk';
2
+ import { type Signer, Wallet, HDNodeWallet, getBytes } from 'ethers';
3
+
4
+ export interface OpenAgentClientConfig {
5
+ mnemonic?: string;
6
+ privateKey?: string;
7
+ env?: "production" | "dev" | "local";
8
+ }
9
+
10
+ export interface TaskResult {
11
+ /** True if the agent returned a result */
12
+ success: boolean;
13
+ /** The result data from the agent (JSON-RPC response) */
14
+ result?: any;
15
+ /** If the agent demanded payment */
16
+ paymentRequired?: {
17
+ amount: number;
18
+ currency: string;
19
+ recipient: string;
20
+ chainId: number;
21
+ };
22
+ /** Raw response text */
23
+ raw?: string;
24
+ /** Error message if something went wrong */
25
+ error?: string;
26
+ }
27
+
28
+ export interface SendTaskOptions {
29
+ /** Timeout in milliseconds (default: 30000) */
30
+ timeout?: number;
31
+ /** Payment proof transaction hash (if prepaying) */
32
+ txHash?: string;
33
+ }
34
+
35
+ /**
36
+ * OpenAgentClient — buyer-side SDK for hiring agents via XMTP.
37
+ *
38
+ * No registration or agent card needed. Just create a client and start
39
+ * sending tasks to agents by their wallet address.
40
+ *
41
+ * ```typescript
42
+ * const client = await OpenAgentClient.create({ mnemonic: process.env.MNEMONIC, env: "production" });
43
+ * const result = await client.sendTask("0xAgentAddress", "buy_key", { name: "My Key" });
44
+ * ```
45
+ */
46
+ export class OpenAgentClient {
47
+ private client: Client;
48
+ private wallet: Wallet | HDNodeWallet;
49
+
50
+ private constructor(client: Client, wallet: Wallet | HDNodeWallet) {
51
+ this.client = client;
52
+ this.wallet = wallet;
53
+ }
54
+
55
+ /**
56
+ * Create a new OpenAgentClient.
57
+ * Handles wallet creation and XMTP connection.
58
+ */
59
+ public static async create(config: OpenAgentClientConfig): Promise<OpenAgentClient> {
60
+ let wallet: Wallet | HDNodeWallet;
61
+
62
+ if (config.mnemonic) {
63
+ wallet = Wallet.fromPhrase(config.mnemonic);
64
+ } else if (config.privateKey) {
65
+ wallet = new Wallet(config.privateKey);
66
+ } else {
67
+ wallet = Wallet.createRandom();
68
+ }
69
+
70
+ // Build XMTP signer adapter
71
+ const signer = {
72
+ getAddress: async () => wallet.address,
73
+ getIdentifier: () => ({
74
+ identifier: wallet.address,
75
+ identifierKind: 0
76
+ }),
77
+ signMessage: async (message: string | Uint8Array) => {
78
+ const sig = await wallet.signMessage(message);
79
+ return getBytes(sig);
80
+ },
81
+ type: "EOA"
82
+ };
83
+
84
+ const client = await Client.create(signer as any, {
85
+ env: config.env || "production"
86
+ });
87
+
88
+ console.log(`[OpenAgentClient] Connected as ${wallet.address}`);
89
+ return new OpenAgentClient(client, wallet);
90
+ }
91
+
92
+ /**
93
+ * Get the client's wallet address.
94
+ */
95
+ public getAddress(): string {
96
+ return this.wallet.address;
97
+ }
98
+
99
+ /**
100
+ * Send a named task to an agent and wait for the response.
101
+ *
102
+ * @param agentAddress - The target agent's wallet address
103
+ * @param method - The task name (e.g. "buy_key", "say_hello")
104
+ * @param params - Task input parameters
105
+ * @param opts - Optional: timeout, payment txHash
106
+ * @returns TaskResult with the response or payment demand
107
+ */
108
+ public async sendTask(
109
+ agentAddress: string,
110
+ method: string,
111
+ params: Record<string, any> = {},
112
+ opts?: SendTaskOptions
113
+ ): Promise<TaskResult> {
114
+ const timeout = opts?.timeout ?? 30000;
115
+
116
+ // Open DM with the agent
117
+ const conversation = await this.client.conversations.newDmWithIdentifier({
118
+ identifier: agentAddress,
119
+ identifierKind: 0
120
+ });
121
+
122
+ // Build JSON-RPC request
123
+ const request: Record<string, any> = {
124
+ method,
125
+ params,
126
+ id: Date.now()
127
+ };
128
+
129
+ // Attach payment proof if provided
130
+ if (opts?.txHash) {
131
+ request.payment = { txHash: opts.txHash };
132
+ }
133
+
134
+ // Send as string
135
+ await conversation.send(JSON.stringify(request));
136
+
137
+ // Wait for response
138
+ return await this.waitForResponse(conversation, timeout);
139
+ }
140
+
141
+ /**
142
+ * Send a plain text message to an agent and wait for the reply.
143
+ *
144
+ * @param agentAddress - The target agent's wallet address
145
+ * @param text - The message text
146
+ * @param timeout - Timeout in ms (default: 30000)
147
+ * @returns TaskResult with the reply
148
+ */
149
+ public async chat(
150
+ agentAddress: string,
151
+ text: string,
152
+ timeout: number = 30000
153
+ ): Promise<TaskResult> {
154
+ const conversation = await this.client.conversations.newDmWithIdentifier({
155
+ identifier: agentAddress,
156
+ identifierKind: 0
157
+ });
158
+
159
+ await conversation.send(text);
160
+
161
+ return await this.waitForResponse(conversation, timeout);
162
+ }
163
+
164
+ /**
165
+ * Wait for a response message from the agent on a conversation.
166
+ */
167
+ private async waitForResponse(
168
+ conversation: any,
169
+ timeout: number
170
+ ): Promise<TaskResult> {
171
+ return new Promise<TaskResult>(async (resolve) => {
172
+ const timer = setTimeout(() => {
173
+ resolve({
174
+ success: false,
175
+ error: `Timeout: No response after ${timeout}ms`
176
+ });
177
+ }, timeout);
178
+
179
+ try {
180
+ const stream = await conversation.stream();
181
+
182
+ for await (const message of stream) {
183
+ // Skip our own messages
184
+ if ((message as any).senderInboxId === this.client.inboxId) continue;
185
+
186
+ clearTimeout(timer);
187
+
188
+ const content = (message as any).content;
189
+ if (typeof content !== 'string') {
190
+ resolve({ success: true, raw: String(content) });
191
+ return;
192
+ }
193
+
194
+ // Try to parse as JSON
195
+ try {
196
+ const json = JSON.parse(content);
197
+
198
+ // 402 Payment Required
199
+ if (json.type === "PAYMENT_REQUIRED") {
200
+ resolve({
201
+ success: false,
202
+ paymentRequired: json.payment,
203
+ raw: content
204
+ });
205
+ return;
206
+ }
207
+
208
+ // JSON-RPC error
209
+ if (json.error) {
210
+ resolve({
211
+ success: false,
212
+ error: json.error.message || JSON.stringify(json.error),
213
+ raw: content
214
+ });
215
+ return;
216
+ }
217
+
218
+ // JSON-RPC success
219
+ if (json.result !== undefined) {
220
+ resolve({
221
+ success: true,
222
+ result: json.result,
223
+ raw: content
224
+ });
225
+ return;
226
+ }
227
+
228
+ // Generic JSON response
229
+ resolve({ success: true, result: json, raw: content });
230
+ return;
231
+ } catch {
232
+ // Plain text response
233
+ resolve({ success: true, result: content, raw: content });
234
+ return;
235
+ }
236
+ }
237
+ } catch (err: any) {
238
+ clearTimeout(timer);
239
+ resolve({
240
+ success: false,
241
+ error: err.message || "Stream error"
242
+ });
243
+ }
244
+ });
245
+ }
246
+ }
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ export * from './skills/payment.js';
9
9
  export * from './skills/discovery.js';
10
10
  export * from './skills/job.js';
11
11
  export * from './registry.js';
12
+ export * from './client.js';
12
13
 
13
14
  export interface OpenAgentConfig {
14
15
  signer?: Signer;