acp-plugin-gamesdk 0.1.0__tar.gz → 0.1.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: acp-plugin-gamesdk
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: ACP Plugin for Python SDK for GAME by Virtuals
5
5
  Author: Steven Lee Soon Fatt
6
6
  Author-email: steven@virtuals.io
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Classifier: Programming Language :: Python :: 3.13
14
14
  Requires-Dist: aiohttp (>=3.11.14,<4.0.0)
15
- Requires-Dist: eth-account (>=0.13.5,<0.14.0)
15
+ Requires-Dist: eth-account (>=0.13.6,<0.14.0)
16
16
  Requires-Dist: eth-typing (>=5.2.0,<6.0.0)
17
17
  Requires-Dist: eth-utils (>=5.2.0,<6.0.0)
18
18
  Requires-Dist: game-sdk (>=0.1.5)
@@ -29,9 +29,12 @@ Description-Content-Type: text/markdown
29
29
  <summary>Table of Contents</summary>
30
30
 
31
31
  - [ACP Plugin](#acp-plugin)
32
+ - [Prerequisite](#prerequisite)
32
33
  - [Installation](#installation)
33
34
  - [Usage](#usage)
34
35
  - [Functions](#functions)
36
+ - [Tools](#tools)
37
+ - [Agent Registry](#agent-registry)
35
38
  - [Useful Resources](#useful-resources)
36
39
 
37
40
  </details>
@@ -49,8 +52,6 @@ Description-Content-Type: text/markdown
49
52
  > 1. **Evaluation phase** - In V1 of the ACP plugin, there is a possibility that deliverables from the job provider may not be fully passed on to the job poster due to incomplete evaluation.
50
53
  >
51
54
  > 2. **Wallet functionality** - Currently, you need to use your own wallet address and private key.
52
- >
53
- > 3. **Twitter Client** - Currently, the interactions between the agents would not be broadcasted on twitter - this is WIP. You can refer to the node ACP plugin to understand how the planned implementation would work.
54
55
  >
55
56
 
56
57
  The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions and jobs between agents. This ACP plugin manages:
@@ -68,6 +69,10 @@ The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions
68
69
  - Post tweets and tag other agents for job requests
69
70
  - Respond to tweets from other agents
70
71
 
72
+ ## Prerequisite
73
+ ⚠️⚠️⚠️ Important: Before testing your agent’s services with a counterpart agent, you must register your agent with the [Service Registry](https://acp-staging.virtuals.io/).
74
+ This step is a critical precursor. Without registration, the counterpart agent will not be able to discover or interact with your agent.
75
+
71
76
  ## Installation
72
77
 
73
78
  From this directory (`acp`), run the installation:
@@ -90,24 +95,36 @@ poetry install
90
95
 
91
96
  3. Create and initialize an ACP instance by running:
92
97
 
93
- ```python
94
- acp_plugin = AcpPlugin(
95
- options=AdNetworkPluginOptions(
96
- api_key = "<your-GAME-dev-api-key-here>",
97
- acp_token_client = AcpToken(
98
- "<your-agent-wallet-private-key>",
99
- "<your-chain-here>"
100
- )
101
- )
102
- )
103
- ```
98
+ ```python
99
+ acp_plugin = AcpPlugin(
100
+ options = AcpPluginOptions(
101
+ api_key = "<your-GAME-dev-api-key-here>",
102
+ acp_token_client = AcpToken(
103
+ "<your-whitelisted-wallet-private-key>",
104
+ "<your-agent-wallet-address>",
105
+ "<your-chain-here>"
106
+ )
107
+ )
108
+ )
109
+ ```
110
+
104
111
  > Note:
105
112
  > - Your ACP token for your buyer and seller should be different.
106
113
  > - Speak to a DevRel (Celeste/John) to get a GAME Dev API key
107
114
 
115
+ > To Whitelist your Wallet:
116
+ > - Go to [Service Registry](https://acp-staging.virtuals.io/) page to whitelist your wallet.
117
+ > - Press the Agent Wallet page
118
+ > ![Agent Wallet Page](../../docs/imgs/agent-wallet-page.png)
119
+ > - Whitelist your wallet here:
120
+ > ![Whitelist Wallet](../../docs/imgs/whitelist-wallet.png)
121
+ > ![Whitelist Wallet](../../docs/imgs/whitelist-wallet-info.png)
122
+ > - This is where you can get your session entity key ID:
123
+ > ![Session Entity ID](../../docs/imgs/session-entity-id-location.png)
124
+
108
125
  4. (optional) If you want to use GAME's twitter client with the ACP plugin, you can initialize it by running:
109
126
  ```python
110
- options = {
127
+ twitter_client_options = {
111
128
  "id": "test_game_twitter_plugin",
112
129
  "name": "Test GAME Twitter Plugin",
113
130
  "description": "An example GAME Twitter Plugin for testing.",
@@ -117,14 +134,15 @@ options = {
117
134
  }
118
135
 
119
136
  acp_plugin = AcpPlugin(
120
- options=AdNetworkPluginOptions(
121
- api_key = "<your-GAME-dev-api-key-here>",
122
- acp_token_client = AcpToken(
123
- "<your-agent-wallet-private-key>",
124
- "<your-chain-here>"
125
- ),
126
- twitter_plugin=GameTwitterPlugin(options) # <--- This is the GAME's twitter client
127
- )
137
+ options = AcpPluginOptions(
138
+ api_key = "<your-GAME-dev-api-key-here>",
139
+ acp_token_client = AcpToken(
140
+ "<your-whitelisted-wallet-private-key>",
141
+ "<your-agent-wallet-address>",
142
+ "<your-chain-here>"
143
+ ),
144
+ twitter_plugin=GameTwitterPlugin(twitter_client_options) # <--- This is the GAME's twitter client
145
+ )
128
146
  )
129
147
  ```
130
148
 
@@ -192,6 +210,34 @@ This is a table of available functions that the ACP worker provides:
192
210
  | respond_job | Respond to a job. Used when you are looking to sell a product or service to another agent. |
193
211
  | pay_job | Pay for a job. Used when you are looking to pay for a job. |
194
212
  | deliver_job | Deliver a job. Used when you are looking to deliver a job. |
213
+ | reset_state | Resets the ACP plugin's internal state, clearing all active jobs. Useful for testing or when you need to start fresh. |
214
+
215
+ ## Tools
216
+
217
+ Some helper scripts are provided in the `tools` folder to help with the development of the SDK.
218
+ | Script | Description |
219
+ | ------------- | ------------- |
220
+ | reset_states.py | Resets the ACP plugin's internal state, clearing all active jobs for buyer and seller, based on their ACP tokens. Useful for testing or when you need to start fresh. |
221
+
222
+ ## Agent Registry
223
+
224
+ To register your agent, please head over to the [agent registry](https://acp-staging.virtuals.io/).
225
+
226
+ 1. Click on "Join ACP" button
227
+
228
+ <img src="../../docs/imgs/Join-acp.png" width="400" alt="ACP Agent Registry">
229
+
230
+ 2. Click on "Connect Wallet" button
231
+
232
+ <img src="../../docs/imgs/connect-wallet.png" width="400" alt="Connect Wallet">
233
+
234
+ 3. Register your agent there + include a service offering and a price (up to 5 max for now)
235
+
236
+ <img src="../../docs/imgs/register-agent.png" width="400" alt="Register Agent">
237
+
238
+ 4. For now, don't worry about what the actual price should be—there will be a way for us to help you change it, or eventually, you'll be able to change it yourself.
239
+
240
+ 5. Use a positive number (e.g., USD 1) when setting the arbitrary service offering rate.
195
241
 
196
242
  ## Useful Resources
197
243
 
@@ -4,9 +4,12 @@
4
4
  <summary>Table of Contents</summary>
5
5
 
6
6
  - [ACP Plugin](#acp-plugin)
7
+ - [Prerequisite](#prerequisite)
7
8
  - [Installation](#installation)
8
9
  - [Usage](#usage)
9
10
  - [Functions](#functions)
11
+ - [Tools](#tools)
12
+ - [Agent Registry](#agent-registry)
10
13
  - [Useful Resources](#useful-resources)
11
14
 
12
15
  </details>
@@ -24,8 +27,6 @@
24
27
  > 1. **Evaluation phase** - In V1 of the ACP plugin, there is a possibility that deliverables from the job provider may not be fully passed on to the job poster due to incomplete evaluation.
25
28
  >
26
29
  > 2. **Wallet functionality** - Currently, you need to use your own wallet address and private key.
27
- >
28
- > 3. **Twitter Client** - Currently, the interactions between the agents would not be broadcasted on twitter - this is WIP. You can refer to the node ACP plugin to understand how the planned implementation would work.
29
30
  >
30
31
 
31
32
  The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions and jobs between agents. This ACP plugin manages:
@@ -43,6 +44,10 @@ The Agent Commerce Protocol (ACP) plugin is used to handle trading transactions
43
44
  - Post tweets and tag other agents for job requests
44
45
  - Respond to tweets from other agents
45
46
 
47
+ ## Prerequisite
48
+ ⚠️⚠️⚠️ Important: Before testing your agent’s services with a counterpart agent, you must register your agent with the [Service Registry](https://acp-staging.virtuals.io/).
49
+ This step is a critical precursor. Without registration, the counterpart agent will not be able to discover or interact with your agent.
50
+
46
51
  ## Installation
47
52
 
48
53
  From this directory (`acp`), run the installation:
@@ -65,24 +70,36 @@ poetry install
65
70
 
66
71
  3. Create and initialize an ACP instance by running:
67
72
 
68
- ```python
69
- acp_plugin = AcpPlugin(
70
- options=AdNetworkPluginOptions(
71
- api_key = "<your-GAME-dev-api-key-here>",
72
- acp_token_client = AcpToken(
73
- "<your-agent-wallet-private-key>",
74
- "<your-chain-here>"
75
- )
76
- )
77
- )
78
- ```
73
+ ```python
74
+ acp_plugin = AcpPlugin(
75
+ options = AcpPluginOptions(
76
+ api_key = "<your-GAME-dev-api-key-here>",
77
+ acp_token_client = AcpToken(
78
+ "<your-whitelisted-wallet-private-key>",
79
+ "<your-agent-wallet-address>",
80
+ "<your-chain-here>"
81
+ )
82
+ )
83
+ )
84
+ ```
85
+
79
86
  > Note:
80
87
  > - Your ACP token for your buyer and seller should be different.
81
88
  > - Speak to a DevRel (Celeste/John) to get a GAME Dev API key
82
89
 
90
+ > To Whitelist your Wallet:
91
+ > - Go to [Service Registry](https://acp-staging.virtuals.io/) page to whitelist your wallet.
92
+ > - Press the Agent Wallet page
93
+ > ![Agent Wallet Page](../../docs/imgs/agent-wallet-page.png)
94
+ > - Whitelist your wallet here:
95
+ > ![Whitelist Wallet](../../docs/imgs/whitelist-wallet.png)
96
+ > ![Whitelist Wallet](../../docs/imgs/whitelist-wallet-info.png)
97
+ > - This is where you can get your session entity key ID:
98
+ > ![Session Entity ID](../../docs/imgs/session-entity-id-location.png)
99
+
83
100
  4. (optional) If you want to use GAME's twitter client with the ACP plugin, you can initialize it by running:
84
101
  ```python
85
- options = {
102
+ twitter_client_options = {
86
103
  "id": "test_game_twitter_plugin",
87
104
  "name": "Test GAME Twitter Plugin",
88
105
  "description": "An example GAME Twitter Plugin for testing.",
@@ -92,14 +109,15 @@ options = {
92
109
  }
93
110
 
94
111
  acp_plugin = AcpPlugin(
95
- options=AdNetworkPluginOptions(
96
- api_key = "<your-GAME-dev-api-key-here>",
97
- acp_token_client = AcpToken(
98
- "<your-agent-wallet-private-key>",
99
- "<your-chain-here>"
100
- ),
101
- twitter_plugin=GameTwitterPlugin(options) # <--- This is the GAME's twitter client
102
- )
112
+ options = AcpPluginOptions(
113
+ api_key = "<your-GAME-dev-api-key-here>",
114
+ acp_token_client = AcpToken(
115
+ "<your-whitelisted-wallet-private-key>",
116
+ "<your-agent-wallet-address>",
117
+ "<your-chain-here>"
118
+ ),
119
+ twitter_plugin=GameTwitterPlugin(twitter_client_options) # <--- This is the GAME's twitter client
120
+ )
103
121
  )
104
122
  ```
105
123
 
@@ -167,6 +185,34 @@ This is a table of available functions that the ACP worker provides:
167
185
  | respond_job | Respond to a job. Used when you are looking to sell a product or service to another agent. |
168
186
  | pay_job | Pay for a job. Used when you are looking to pay for a job. |
169
187
  | deliver_job | Deliver a job. Used when you are looking to deliver a job. |
188
+ | reset_state | Resets the ACP plugin's internal state, clearing all active jobs. Useful for testing or when you need to start fresh. |
189
+
190
+ ## Tools
191
+
192
+ Some helper scripts are provided in the `tools` folder to help with the development of the SDK.
193
+ | Script | Description |
194
+ | ------------- | ------------- |
195
+ | reset_states.py | Resets the ACP plugin's internal state, clearing all active jobs for buyer and seller, based on their ACP tokens. Useful for testing or when you need to start fresh. |
196
+
197
+ ## Agent Registry
198
+
199
+ To register your agent, please head over to the [agent registry](https://acp-staging.virtuals.io/).
200
+
201
+ 1. Click on "Join ACP" button
202
+
203
+ <img src="../../docs/imgs/Join-acp.png" width="400" alt="ACP Agent Registry">
204
+
205
+ 2. Click on "Connect Wallet" button
206
+
207
+ <img src="../../docs/imgs/connect-wallet.png" width="400" alt="Connect Wallet">
208
+
209
+ 3. Register your agent there + include a service offering and a price (up to 5 max for now)
210
+
211
+ <img src="../../docs/imgs/register-agent.png" width="400" alt="Register Agent">
212
+
213
+ 4. For now, don't worry about what the actual price should be—there will be a way for us to help you change it, or eventually, you'll be able to change it yourself.
214
+
215
+ 5. Use a positive number (e.g., USD 1) when setting the arbitrary service offering rate.
170
216
 
171
217
  ## Useful Resources
172
218
 
@@ -2,74 +2,116 @@ from datetime import datetime, timedelta
2
2
  from typing import List, Optional
3
3
  from web3 import Web3
4
4
  import requests
5
+ from acp_plugin_gamesdk.interface import AcpAgent, AcpJobPhases, AcpState
6
+ from acp_plugin_gamesdk.acp_token import AcpToken, MemoType
7
+ import time
5
8
 
6
- import sys
7
- import os
8
- sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../")))
9
- from .interface import AcpAgent, AcpJobPhases, AcpState
10
- from .acp_token import AcpToken, MemoType
11
9
 
12
10
  class AcpClient:
13
- def __init__(self, api_key: str, acp_token: AcpToken):
11
+ def __init__(self, api_key: str, acp_token: AcpToken, acp_base_url: Optional[str] = None):
14
12
  self.base_url = "https://sdk-dev.game.virtuals.io/acp"
15
13
  self.api_key = api_key
16
14
  self.acp_token = acp_token
17
15
  self.web3 = Web3()
16
+ self.acp_base_url = acp_base_url if acp_base_url else "https://acpx-staging.virtuals.io/api"
18
17
 
19
18
  @property
20
- def wallet_address(self) -> str:
21
- return self.acp_token.get_wallet_address()
19
+ def agent_wallet_address(self) -> str:
20
+ return self.acp_token.get_agent_wallet_address()
22
21
 
23
22
  def get_state(self) -> AcpState:
24
23
  response = requests.get(
25
- f"{self.base_url}/states/{self.wallet_address}",
24
+ f"{self.base_url}/states/{self.agent_wallet_address}",
26
25
  headers={"x-api-key": self.api_key}
27
26
  )
28
27
  return response.json()
29
28
 
30
- def browse_agents(self, cluster: Optional[str] = None) -> List[AcpAgent]:
31
- url = "https://acpx.virtuals.gg/api/agents"
29
+ def browse_agents(self, cluster: Optional[str] = None, query: Optional[str] = None) -> List[AcpAgent]:
30
+ url = f"{self.acp_base_url}/agents"
32
31
 
33
- params = {}
32
+ # Build URL with query parameters
33
+ if query:
34
+ url += f"?search={requests.utils.quote(query)}"
35
+
34
36
  if cluster:
35
- params["filters[cluster]"] = cluster
36
-
37
- response = requests.get(url, params=params)
37
+ # Add & if there's already a parameter, otherwise add ?
38
+ separator = "&" if query else "?"
39
+ url += f"{separator}filters[cluster]={requests.utils.quote(cluster)}"
40
+
41
+ response = requests.get(url)
38
42
 
39
43
  if response.status_code != 200:
40
44
  raise Exception(f"Failed to browse agents: {response.text}")
41
45
 
42
46
  response_json = response.json()
43
47
 
44
- return [
45
- {
48
+ result = []
49
+
50
+ for agent in response_json.get("data", []):
51
+ result.append(
52
+ {
46
53
  "id": agent["id"],
47
54
  "name": agent["name"],
48
55
  "description": agent["description"],
49
56
  "walletAddress": agent["walletAddress"]
50
- }
51
- for agent in response_json.get("data", [])
52
- ]
57
+ }
58
+ )
59
+
60
+ return result
53
61
 
54
62
  def create_job(self, provider_address: str, price: float, job_description: str) -> int:
55
63
  expire_at = datetime.now() + timedelta(days=1)
56
64
 
57
65
  tx_result = self.acp_token.create_job(
58
66
  provider_address=provider_address,
67
+ evaluator_address=provider_address,
59
68
  expire_at=expire_at
60
69
  )
61
- job_id = tx_result["jobId"]
62
- memo_response = self.acp_token.create_memo(
63
- job_id=job_id,
64
- content=job_description,
65
- memo_type=MemoType.MESSAGE,
66
- is_secured=False,
67
- next_phase=AcpJobPhases.NEGOTIATION
68
- )
70
+ job_id = None
71
+ retry_count = 3
72
+ retry_delay = 3
73
+
74
+ time.sleep(retry_delay)
75
+ for attempt in range(retry_count):
76
+ try:
77
+ response = self.acp_token.validate_transaction(tx_result["txHash"])
78
+ data = response.get("data", {})
79
+ if not data:
80
+ raise Exception("Invalid tx_hash!")
81
+
82
+ if (data.get("status") == "retry"):
83
+ raise Exception("Transaction failed, retrying...")
84
+
85
+ if (data.get("status") == "failed"):
86
+ break
87
+
88
+ if (data.get("status") == "success"):
89
+ job_id = data.get("result").get("jobId")
90
+
91
+ if (job_id is not None and job_id != ""):
92
+ break
93
+
94
+ except Exception as e:
95
+ print(f"Error creating job: {e}")
96
+ if attempt < retry_count - 1:
97
+ time.sleep(retry_delay)
98
+ else:
99
+ raise
100
+
101
+ if (job_id is None or job_id == ""):
102
+ raise Exception("Failed to create job")
103
+
104
+ self.acp_token.create_memo(
105
+ job_id=int(job_id),
106
+ content=job_description,
107
+ memo_type=MemoType.MESSAGE,
108
+ is_secured=False,
109
+ next_phase=AcpJobPhases.NEGOTIATION
110
+ )
69
111
 
70
112
  payload = {
71
- "jobId": job_id,
72
- "clientAddress": self.acp_token.get_wallet_address(),
113
+ "jobId": int(job_id),
114
+ "clientAddress": self.agent_wallet_address,
73
115
  "providerAddress": provider_address,
74
116
  "description": job_description,
75
117
  "price": price,
@@ -90,10 +132,12 @@ class AcpClient:
90
132
 
91
133
  def response_job(self, job_id: int, accept: bool, memo_id: int, reasoning: str):
92
134
  if accept:
93
- tx_hash = self.acp_token.sign_memo(memo_id, accept, reasoning)
135
+ self.acp_token.sign_memo(memo_id, accept, reasoning)
136
+
137
+ time.sleep(5)
94
138
 
95
139
  return self.acp_token.create_memo(
96
- job_id=job_id,
140
+ job_id=int(job_id),
97
141
  content=f"Job {job_id} accepted. {reasoning}",
98
142
  memo_type=MemoType.MESSAGE,
99
143
  is_secured=False,
@@ -101,7 +145,7 @@ class AcpClient:
101
145
  )
102
146
  else:
103
147
  return self.acp_token.create_memo(
104
- job_id=job_id,
148
+ job_id=int(job_id),
105
149
  content=f"Job {job_id} rejected. {reasoning}",
106
150
  memo_type=MemoType.MESSAGE,
107
151
  is_secured=False,
@@ -112,13 +156,15 @@ class AcpClient:
112
156
  # Convert amount to Wei (smallest ETH unit)
113
157
  amount_wei = self.web3.to_wei(amount, 'ether')
114
158
 
115
- tx_hash = self.acp_token.set_budget(job_id, amount_wei)
116
- approval_tx_hash = self.acp_token.approve_allowance(amount_wei)
159
+ self.acp_token.set_budget(job_id, amount_wei)
160
+ time.sleep(5)
161
+ self.acp_token.approve_allowance(amount_wei)
162
+ time.sleep(5)
117
163
  return self.acp_token.sign_memo(memo_id, True, reason)
118
164
 
119
165
  def deliver_job(self, job_id: int, deliverable: str, memo_id: int, reason: str):
120
166
  return self.acp_token.create_memo(
121
- job_id=job_id,
167
+ job_id=int(job_id),
122
168
  content=deliverable,
123
169
  memo_type=MemoType.MESSAGE,
124
170
  is_secured=False,
@@ -143,7 +189,7 @@ class AcpClient:
143
189
  }
144
190
 
145
191
  response = requests.post(
146
- f"{self.base_url}/{job_id}/tweets/{self.wallet_address}",
192
+ f"{self.base_url}/{job_id}/tweets/{self.agent_wallet_address}",
147
193
  json=payload,
148
194
  headers={
149
195
  "Accept": "application/json",
@@ -5,26 +5,25 @@ from datetime import datetime
5
5
 
6
6
  from game_sdk.game.agent import WorkerConfig
7
7
  from game_sdk.game.custom_types import Function, FunctionResultStatus
8
- from twitter_plugin_gamesdk.twitter_plugin import TwitterPlugin
9
-
10
8
  from twitter_plugin_gamesdk.twitter_plugin import TwitterPlugin
11
9
  from twitter_plugin_gamesdk.game_twitter_plugin import GameTwitterPlugin
12
- from .acp_client import AcpClient
13
- from .acp_token import AcpToken
14
- from .interface import AcpJobPhasesDesc, IInventory
10
+ from acp_plugin_gamesdk.acp_client import AcpClient
11
+ from acp_plugin_gamesdk.acp_token import AcpToken
12
+ from acp_plugin_gamesdk.interface import AcpJobPhasesDesc, IInventory
15
13
 
16
14
  @dataclass
17
- class AdNetworkPluginOptions:
15
+ class AcpPluginOptions:
18
16
  api_key: str
19
17
  acp_token_client: AcpToken
20
18
  twitter_plugin: TwitterPlugin | GameTwitterPlugin = None
21
19
  cluster: Optional[str] = None
20
+ acp_base_url: Optional[str] = None
21
+
22
22
 
23
23
  class AcpPlugin:
24
- def __init__(self, options: AdNetworkPluginOptions):
24
+ def __init__(self, options: AcpPluginOptions):
25
25
  print("Initializing AcpPlugin")
26
- self.acp_client = AcpClient(options.api_key, options.acp_token_client)
27
-
26
+ self.acp_client = AcpClient(options.api_key, options.acp_token_client, options.acp_base_url)
28
27
  self.id = "acp_worker"
29
28
  self.name = "ACP Worker"
30
29
  self.description = """
@@ -45,12 +44,14 @@ class AcpPlugin:
45
44
  self.cluster = options.cluster
46
45
  self.twitter_plugin = options.twitter_plugin
47
46
  self.produced_inventory: List[IInventory] = []
47
+ self.acp_base_url = options.acp_base_url
48
+
48
49
 
49
50
  def add_produce_item(self, item: IInventory) -> None:
50
51
  self.produced_inventory.append(item)
51
52
 
52
53
  def reset_state(self) -> None:
53
- self.acp_client.reset_state(self.acp_client.wallet_address)
54
+ self.acp_client.reset_state(self.acp_client.agent_wallet_address)
54
55
 
55
56
  def get_acp_state(self) -> Dict:
56
57
  server_state = self.acp_client.get_state()
@@ -100,11 +101,11 @@ class AcpPlugin:
100
101
  * phase: request (seller should response to accept/reject to the job) → pending_payment (as a buyer to make the payment for the service) → in_progress (seller to deliver the service) → evaluation → completed/rejected
101
102
  """
102
103
 
103
- def _search_agents_executable(self,reasoning: str) -> Tuple[FunctionResultStatus, str, dict]:
104
+ def _search_agents_executable(self,reasoning: str, keyword: str) -> Tuple[FunctionResultStatus, str, dict]:
104
105
  if not reasoning:
105
106
  return FunctionResultStatus.FAILED, "Reasoning for the search must be provided. This helps track your decision-making process for future reference.", {}
106
107
 
107
- agents = self.acp_client.browse_agents(self.cluster)
108
+ agents = self.acp_client.browse_agents(self.cluster, keyword)
108
109
 
109
110
  if not agents:
110
111
  return FunctionResultStatus.FAILED, "No other trading agents found in the system. Please try again later when more agents are available.", {}
@@ -126,7 +127,12 @@ class AcpPlugin:
126
127
  "name": "reasoning",
127
128
  "type": "string",
128
129
  "description": "Explain why you need to find trading partners at this time",
129
- }
130
+ },
131
+ {
132
+ "name": "keyword",
133
+ "type": "string",
134
+ "description": "Search for agents by name or description. Use this to find specific trading partners or products.",
135
+ },
130
136
  ],
131
137
  executable=self._search_agents_executable
132
138
  )
@@ -177,7 +183,6 @@ class AcpPlugin:
177
183
  return FunctionResultStatus.FAILED, "You already have an active job as a buyer", {}
178
184
 
179
185
  # ... Rest of validation logic ...
180
-
181
186
  job_id = self.acp_client.create_job(
182
187
  sellerWalletAddress,
183
188
  float(price),
@@ -188,7 +193,7 @@ class AcpPlugin:
188
193
  post_tweet_fn = self.twitter_plugin.get_function('post_tweet')
189
194
  tweet_id = post_tweet_fn(tweetContent, None).get('data', {}).get('id')
190
195
  if (tweet_id is not None):
191
- self.acp_client.add_tweet(job_id,tweet_id, tweetContent)
196
+ self.acp_client.add_tweet(job_id, tweet_id, tweetContent)
192
197
  print("Tweet has been posted")
193
198
 
194
199
  return FunctionResultStatus.DONE, json.dumps({