mech-client 0.2.15__tar.gz → 0.2.16__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.
Files changed (44) hide show
  1. {mech_client-0.2.15 → mech_client-0.2.16}/PKG-INFO +145 -5
  2. {mech_client-0.2.15 → mech_client-0.2.16}/README.md +143 -4
  3. mech_client-0.2.16/mech_client/__init__.py +3 -0
  4. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/cli.py +95 -2
  5. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/interact.py +15 -13
  6. mech_client-0.2.16/mech_client/mech_tool_management.py +181 -0
  7. {mech_client-0.2.15 → mech_client-0.2.16}/pyproject.toml +2 -1
  8. mech_client-0.2.15/mech_client/__init__.py +0 -3
  9. {mech_client-0.2.15 → mech_client-0.2.16}/LICENSE +0 -0
  10. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/acn.py +0 -0
  11. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/configs/mechs.json +0 -0
  12. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/__init__.py +0 -0
  13. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/README.md +0 -0
  14. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/__init__.py +0 -0
  15. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/acn.proto +0 -0
  16. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/acn_pb2.py +0 -0
  17. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/custom_types.py +0 -0
  18. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/dialogues.py +0 -0
  19. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/message.py +0 -0
  20. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/protocol.yaml +0 -0
  21. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/serialization.py +0 -0
  22. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/tests/__init__.py +0 -0
  23. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/tests/test_acn.py +0 -0
  24. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/tests/test_acn_dialogues.py +0 -0
  25. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn/tests/test_acn_messages.py +0 -0
  26. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/README.md +0 -0
  27. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/__init__.py +0 -0
  28. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/acn_data_share.proto +0 -0
  29. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/acn_data_share_pb2.py +0 -0
  30. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/dialogues.py +0 -0
  31. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/message.py +0 -0
  32. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/protocol.yaml +0 -0
  33. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/serialization.py +0 -0
  34. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/tests/test_acn_data_share_dialogues.py +0 -0
  35. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/acn_data_share/tests/test_acn_data_share_messages.py +0 -0
  36. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/p2p_libp2p_client/README.md +0 -0
  37. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/p2p_libp2p_client/__init__.py +0 -0
  38. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/p2p_libp2p_client/connection.py +0 -0
  39. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/helpers/p2p_libp2p_client/connection.yaml +0 -0
  40. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/prompt_to_ipfs.py +0 -0
  41. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/push_to_ipfs.py +0 -0
  42. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/subgraph.py +0 -0
  43. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/to_png.py +0 -0
  44. {mech_client-0.2.15 → mech_client-0.2.16}/mech_client/wss.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mech-client
3
- Version: 0.2.15
3
+ Version: 0.2.16
4
4
  Summary: Basic client to interact with a mech
5
5
  License: Apache-2.0
6
6
  Author: David Minarsch
@@ -16,6 +16,7 @@ Requires-Dist: open-aea-cli-ipfs (>=1.53.0,<2.0.0)
16
16
  Requires-Dist: open-aea-ledger-cosmos (>=1.53.0,<2.0.0)
17
17
  Requires-Dist: open-aea-ledger-ethereum (>=1.53.0,<2.0.0)
18
18
  Requires-Dist: open-aea[cli] (>=1.53.0,<2.0.0)
19
+ Requires-Dist: tabulate (>=0.9.0,<0.10.0)
19
20
  Requires-Dist: websocket-client (>=0.32.0,<1)
20
21
  Description-Content-Type: text/markdown
21
22
 
@@ -69,10 +70,14 @@ Options:
69
70
  --help Show this message and exit.
70
71
 
71
72
  Commands:
72
- interact Interact with a mech specifying a prompt and tool.
73
- prompt-to-ipfs Upload a prompt and tool to IPFS as metadata.
74
- push-to-ipfs Upload a file to IPFS.
75
- to-png Convert a stability AI API's diffusion model output...
73
+ interact Interact with a mech specifying a prompt and tool.
74
+ prompt-to-ipfs Upload a prompt and tool to IPFS as metadata.
75
+ push-to-ipfs Upload a file to IPFS.
76
+ to-png Convert a stability AI API's diffusion model output.
77
+ tools-for-agents List tools available for all agents or a specific agent.
78
+ tool-description Get the description of a specific tool.
79
+ tool_io_schema Get the input/output schema of a specific tool.
80
+
76
81
  ```
77
82
 
78
83
  ### Set up the EOA and private key
@@ -173,6 +178,102 @@ Data arrived: https://gateway.autonolas.tech/ipfs/f01701220a462120d5bb03f406fa5e
173
178
  Data from agent: {'requestId': 100407405856633966395081711430940962809568685031934329025999216833965518452765, 'result': "In a world of chaos and strife,\nThere's beauty in the simplest of life.\nA gentle breeze whispers through the trees,\nAnd birds sing melodies with ease.\n\nThe sun sets in a fiery hue,\nPainting the sky in shades of blue.\nStars twinkle in the darkness above,\nGuiding us with their light and love.\n\nSo take a moment to pause and see,\nThe wonders of this world so free.\nEmbrace the joy that each day brings,\nAnd let your heart soar on gentle wings.", 'prompt': 'write a short poem', 'cost_dict': {}, 'metadata': {'model': None, 'tool': 'openai-gpt-3.5-turbo'}}
174
179
  ```
175
180
 
181
+
182
+ ### List tools available for agents
183
+
184
+ To list the tools available for a specific agent or for all agents, use the `tools-for-agents` command. You can specify an agent ID to get tools for a specific agent, or omit it to list tools for all agents.
185
+
186
+ ```bash
187
+ mechx tools-for-agents
188
+ ```
189
+ ```bash
190
+ You will see an output like this:
191
+ +------------+---------------------------------------------+-----------------------------------------------+
192
+ | Agent ID | Tool Name | UniqueIdentifier |
193
+ +============+=============================================+===============================================+
194
+ | 3 | claude-prediction-offline | 3-claude-prediction-offline |
195
+ +------------+---------------------------------------------+-----------------------------------------------+
196
+ | 3 | claude-prediction-online | 3-claude-prediction-online |
197
+ +------------+---------------------------------------------+-----------------------------------------------+
198
+ | 3 | deepmind-optimization | 3-deepmind-optimization |
199
+ +------------+---------------------------------------------+-----------------------------------------------+
200
+ | 3 | deepmind-optimization-strong | 3-deepmind-optimization-strong |
201
+ +------------+---------------------------------------------+-----------------------------------------------+
202
+ ```
203
+
204
+ ```bash
205
+ mechx tools-for-agents --agent-id "agent_id"
206
+ ```
207
+ Eaxmple usage
208
+ ```bash
209
+ mechx tools-for-agents --agent-id 6
210
+ ```
211
+ ```bash
212
+ You will see an output like this:
213
+ +---------------------------------------------+-----------------------------------------------+
214
+ | Tool Name | Unique Identifier |
215
+ +=============================================+===============================================+
216
+ | claude-prediction-offline | 6-claude-prediction-offline |
217
+ +---------------------------------------------+-----------------------------------------------+
218
+ | claude-prediction-online | 6-claude-prediction-online |
219
+ +---------------------------------------------+-----------------------------------------------+
220
+ | deepmind-optimization | 6-deepmind-optimization |
221
+ +---------------------------------------------+-----------------------------------------------+
222
+ ```
223
+
224
+ ### Get Tool Description
225
+
226
+ To get the description of a specific tool, use the `tool-description` command. You need to specify the unique identifier of the tool.
227
+
228
+ ```bash
229
+ mechx tool-description --unique-identifier <unique_identifier> --chain-config <chain_config>
230
+ ```
231
+ Example usage:
232
+
233
+ ```bash
234
+ mechx tool-description --unique-identifier "6-claude-prediction-offline" --chain-config gnosis
235
+ ```
236
+ You will see an output like this:
237
+ ```bash
238
+ Description for tool 6-claude-prediction-offline: Makes a prediction using Claude
239
+ ```
240
+
241
+
242
+ ### Get Tool Input/Output Schema
243
+
244
+ To get the input/output schema of a specific tool, use the `tool_io_schema` command. You need to specify the unique identifier of the tool.
245
+
246
+ ```bash
247
+ mechx tool-io-schema --unique-identifier <unique_identifier> --chain-config <chain_config>
248
+ ```
249
+
250
+ Example usage:
251
+
252
+ ```bash
253
+ mechx tool-io-schema --unique-identifier "6-prediction-offline" --chain-config gnosis
254
+ ```
255
+ You will see an output like this:
256
+ ```bash
257
+ Input Schema:
258
+ +-------------+----------------------------------+
259
+ | Field | Value |
260
+ +=============+==================================+
261
+ | type | text |
262
+ +-------------+----------------------------------+
263
+ | description | The text to make a prediction on |
264
+ +-------------+----------------------------------+
265
+ Output Schema:
266
+ +-----------+---------+-----------------------------------------------+
267
+ | Field | Type | Description |
268
+ +===========+=========+===============================================+
269
+ | requestId | integer | Unique identifier for the request |
270
+ +-----------+---------+-----------------------------------------------+
271
+ | result | string | Result information in JSON format as a string |
272
+ +-----------+---------+-----------------------------------------------+
273
+ | prompt | string | Prompt used for probability estimation. |
274
+ +-----------+---------+-----------------------------------------------+
275
+ ```
276
+
176
277
  > **:pencil2: Note** <br />
177
278
  > **If you encounter an "Out of gas" error when executing the Mech Client, you will need to increase the gas limit, e.g.,**
178
279
  >
@@ -235,6 +336,45 @@ You can also use the Mech Client as a library on your Python project.
235
336
  print(result)
236
337
  ```
237
338
 
339
+ You can also use the Mech Client to programmatically fetch tools for agents in your Python project, as well as retrieve descriptions and input/output schemas for specific tools given their unique identifier.
340
+
341
+ 1. Set up the private key as specified [above](#set-up-the-private-key). Store the resulting key file (e.g., `ethereum_private_key.txt`) in a convenient and secure location.
342
+
343
+ 2. Create a Python script `fetch_tools_script.py`:
344
+
345
+ ```bash
346
+ touch fetch_tools_script.py
347
+ ```
348
+
349
+ 3. Edit `fetch_tools_script.py` as follows:
350
+
351
+ ```python
352
+ from mech_client.mech_tool_management import get_tools_for_agents, get_tool_description, get_tool_io_schema
353
+
354
+ # Fetching tools for a specific agent or all agents
355
+ agent_id = 6 # Specify the agent ID or set to None to fetch tools for all agents
356
+ chain_config = "gnosis" # Specify the chain configuration
357
+ tools = get_tools_for_agents(agent_id=agent_id, chain_config=chain_config)
358
+ print(f"Tools for agent {agent_id}:", tools)
359
+
360
+ # Assuming you know the tool name, construct the unique identifier
361
+ tool_name = "claude-prediction-offline" # Example tool name
362
+ unique_identifier = f"{agent_id}-{tool_name}" # Construct the unique identifier
363
+
364
+ # Fetching description and I/O schema for a specific tool using the unique identifier
365
+ description = get_tool_description(unique_identifier, chain_config)
366
+ print(f"Description for {unique_identifier}:", description)
367
+
368
+ io_schema = get_tool_io_schema(unique_identifier, chain_config)
369
+ print(f"Input/Output Schema for {unique_identifier}:", io_schema)
370
+ ```
371
+
372
+ This script will:
373
+ - Fetch and print the tools available for a specified agent or for all agents if `agent_id` is set to `None`.
374
+ - Construct the unique identifier for a tool using the format `agentId-toolName`.
375
+ - Retrieve and display the description of a specific tool using its unique identifier.
376
+ - Retrieve and display the input and output schema of a specific tool using its unique identifier.
377
+
238
378
  ## Developer installation
239
379
 
240
380
  To setup the development environment for this project, clone the repository and run the following commands:
@@ -48,10 +48,14 @@ Options:
48
48
  --help Show this message and exit.
49
49
 
50
50
  Commands:
51
- interact Interact with a mech specifying a prompt and tool.
52
- prompt-to-ipfs Upload a prompt and tool to IPFS as metadata.
53
- push-to-ipfs Upload a file to IPFS.
54
- to-png Convert a stability AI API's diffusion model output...
51
+ interact Interact with a mech specifying a prompt and tool.
52
+ prompt-to-ipfs Upload a prompt and tool to IPFS as metadata.
53
+ push-to-ipfs Upload a file to IPFS.
54
+ to-png Convert a stability AI API's diffusion model output.
55
+ tools-for-agents List tools available for all agents or a specific agent.
56
+ tool-description Get the description of a specific tool.
57
+ tool_io_schema Get the input/output schema of a specific tool.
58
+
55
59
  ```
56
60
 
57
61
  ### Set up the EOA and private key
@@ -152,6 +156,102 @@ Data arrived: https://gateway.autonolas.tech/ipfs/f01701220a462120d5bb03f406fa5e
152
156
  Data from agent: {'requestId': 100407405856633966395081711430940962809568685031934329025999216833965518452765, 'result': "In a world of chaos and strife,\nThere's beauty in the simplest of life.\nA gentle breeze whispers through the trees,\nAnd birds sing melodies with ease.\n\nThe sun sets in a fiery hue,\nPainting the sky in shades of blue.\nStars twinkle in the darkness above,\nGuiding us with their light and love.\n\nSo take a moment to pause and see,\nThe wonders of this world so free.\nEmbrace the joy that each day brings,\nAnd let your heart soar on gentle wings.", 'prompt': 'write a short poem', 'cost_dict': {}, 'metadata': {'model': None, 'tool': 'openai-gpt-3.5-turbo'}}
153
157
  ```
154
158
 
159
+
160
+ ### List tools available for agents
161
+
162
+ To list the tools available for a specific agent or for all agents, use the `tools-for-agents` command. You can specify an agent ID to get tools for a specific agent, or omit it to list tools for all agents.
163
+
164
+ ```bash
165
+ mechx tools-for-agents
166
+ ```
167
+ ```bash
168
+ You will see an output like this:
169
+ +------------+---------------------------------------------+-----------------------------------------------+
170
+ | Agent ID | Tool Name | UniqueIdentifier |
171
+ +============+=============================================+===============================================+
172
+ | 3 | claude-prediction-offline | 3-claude-prediction-offline |
173
+ +------------+---------------------------------------------+-----------------------------------------------+
174
+ | 3 | claude-prediction-online | 3-claude-prediction-online |
175
+ +------------+---------------------------------------------+-----------------------------------------------+
176
+ | 3 | deepmind-optimization | 3-deepmind-optimization |
177
+ +------------+---------------------------------------------+-----------------------------------------------+
178
+ | 3 | deepmind-optimization-strong | 3-deepmind-optimization-strong |
179
+ +------------+---------------------------------------------+-----------------------------------------------+
180
+ ```
181
+
182
+ ```bash
183
+ mechx tools-for-agents --agent-id "agent_id"
184
+ ```
185
+ Eaxmple usage
186
+ ```bash
187
+ mechx tools-for-agents --agent-id 6
188
+ ```
189
+ ```bash
190
+ You will see an output like this:
191
+ +---------------------------------------------+-----------------------------------------------+
192
+ | Tool Name | Unique Identifier |
193
+ +=============================================+===============================================+
194
+ | claude-prediction-offline | 6-claude-prediction-offline |
195
+ +---------------------------------------------+-----------------------------------------------+
196
+ | claude-prediction-online | 6-claude-prediction-online |
197
+ +---------------------------------------------+-----------------------------------------------+
198
+ | deepmind-optimization | 6-deepmind-optimization |
199
+ +---------------------------------------------+-----------------------------------------------+
200
+ ```
201
+
202
+ ### Get Tool Description
203
+
204
+ To get the description of a specific tool, use the `tool-description` command. You need to specify the unique identifier of the tool.
205
+
206
+ ```bash
207
+ mechx tool-description --unique-identifier <unique_identifier> --chain-config <chain_config>
208
+ ```
209
+ Example usage:
210
+
211
+ ```bash
212
+ mechx tool-description --unique-identifier "6-claude-prediction-offline" --chain-config gnosis
213
+ ```
214
+ You will see an output like this:
215
+ ```bash
216
+ Description for tool 6-claude-prediction-offline: Makes a prediction using Claude
217
+ ```
218
+
219
+
220
+ ### Get Tool Input/Output Schema
221
+
222
+ To get the input/output schema of a specific tool, use the `tool_io_schema` command. You need to specify the unique identifier of the tool.
223
+
224
+ ```bash
225
+ mechx tool-io-schema --unique-identifier <unique_identifier> --chain-config <chain_config>
226
+ ```
227
+
228
+ Example usage:
229
+
230
+ ```bash
231
+ mechx tool-io-schema --unique-identifier "6-prediction-offline" --chain-config gnosis
232
+ ```
233
+ You will see an output like this:
234
+ ```bash
235
+ Input Schema:
236
+ +-------------+----------------------------------+
237
+ | Field | Value |
238
+ +=============+==================================+
239
+ | type | text |
240
+ +-------------+----------------------------------+
241
+ | description | The text to make a prediction on |
242
+ +-------------+----------------------------------+
243
+ Output Schema:
244
+ +-----------+---------+-----------------------------------------------+
245
+ | Field | Type | Description |
246
+ +===========+=========+===============================================+
247
+ | requestId | integer | Unique identifier for the request |
248
+ +-----------+---------+-----------------------------------------------+
249
+ | result | string | Result information in JSON format as a string |
250
+ +-----------+---------+-----------------------------------------------+
251
+ | prompt | string | Prompt used for probability estimation. |
252
+ +-----------+---------+-----------------------------------------------+
253
+ ```
254
+
155
255
  > **:pencil2: Note** <br />
156
256
  > **If you encounter an "Out of gas" error when executing the Mech Client, you will need to increase the gas limit, e.g.,**
157
257
  >
@@ -214,6 +314,45 @@ You can also use the Mech Client as a library on your Python project.
214
314
  print(result)
215
315
  ```
216
316
 
317
+ You can also use the Mech Client to programmatically fetch tools for agents in your Python project, as well as retrieve descriptions and input/output schemas for specific tools given their unique identifier.
318
+
319
+ 1. Set up the private key as specified [above](#set-up-the-private-key). Store the resulting key file (e.g., `ethereum_private_key.txt`) in a convenient and secure location.
320
+
321
+ 2. Create a Python script `fetch_tools_script.py`:
322
+
323
+ ```bash
324
+ touch fetch_tools_script.py
325
+ ```
326
+
327
+ 3. Edit `fetch_tools_script.py` as follows:
328
+
329
+ ```python
330
+ from mech_client.mech_tool_management import get_tools_for_agents, get_tool_description, get_tool_io_schema
331
+
332
+ # Fetching tools for a specific agent or all agents
333
+ agent_id = 6 # Specify the agent ID or set to None to fetch tools for all agents
334
+ chain_config = "gnosis" # Specify the chain configuration
335
+ tools = get_tools_for_agents(agent_id=agent_id, chain_config=chain_config)
336
+ print(f"Tools for agent {agent_id}:", tools)
337
+
338
+ # Assuming you know the tool name, construct the unique identifier
339
+ tool_name = "claude-prediction-offline" # Example tool name
340
+ unique_identifier = f"{agent_id}-{tool_name}" # Construct the unique identifier
341
+
342
+ # Fetching description and I/O schema for a specific tool using the unique identifier
343
+ description = get_tool_description(unique_identifier, chain_config)
344
+ print(f"Description for {unique_identifier}:", description)
345
+
346
+ io_schema = get_tool_io_schema(unique_identifier, chain_config)
347
+ print(f"Input/Output Schema for {unique_identifier}:", io_schema)
348
+ ```
349
+
350
+ This script will:
351
+ - Fetch and print the tools available for a specified agent or for all agents if `agent_id` is set to `None`.
352
+ - Construct the unique identifier for a tool using the format `agentId-toolName`.
353
+ - Retrieve and display the description of a specific tool using its unique identifier.
354
+ - Retrieve and display the input and output schema of a specific tool using its unique identifier.
355
+
217
356
  ## Developer installation
218
357
 
219
358
  To setup the development environment for this project, clone the repository and run the following commands:
@@ -0,0 +1,3 @@
1
+ """Mech client."""
2
+
3
+ __version__ = "0.2.16"
@@ -18,14 +18,20 @@
18
18
  # ------------------------------------------------------------------------------
19
19
 
20
20
  """Mech client CLI module."""
21
-
22
- from typing import Any, Dict, List, Optional
21
+ import json
22
+ from typing import Any, Dict, List, Optional, Tuple
23
23
 
24
24
  import click
25
+ from tabulate import tabulate # type: ignore
25
26
 
26
27
  from mech_client import __version__
27
28
  from mech_client.interact import ConfirmationType
28
29
  from mech_client.interact import interact as interact_
30
+ from mech_client.mech_tool_management import (
31
+ get_tool_description,
32
+ get_tool_io_schema,
33
+ get_tools_for_agents,
34
+ )
29
35
  from mech_client.prompt_to_ipfs import main as prompt_to_ipfs_main
30
36
  from mech_client.push_to_ipfs import main as push_to_ipfs_main
31
37
  from mech_client.to_png import main as to_png_main
@@ -148,10 +154,97 @@ def to_png(ipfs_hash: str, path: str, request_id: str) -> None:
148
154
  to_png_main(ipfs_hash, path, request_id)
149
155
 
150
156
 
157
+ @click.command(name="tools-for-agents")
158
+ @click.option(
159
+ "--agent-id",
160
+ type=int,
161
+ help="Agent ID to fetch tools for. If not provided, fetches for all agents.",
162
+ )
163
+ @click.option("--chain-config", default="gnosis", help="Chain configuration to use.")
164
+ def tools_for_agents(agent_id: Optional[int], chain_config: str) -> None:
165
+ """Fetch and display tools for agents."""
166
+ try:
167
+ result = get_tools_for_agents(agent_id, chain_config)
168
+
169
+ if agent_id is not None:
170
+ headers = ["Tool Name", "Unique Identifier"]
171
+ data: List[Tuple[str, ...]] = [
172
+ (str(tool["tool_name"]), str(tool["unique_identifier"]))
173
+ for tool in result["tools"]
174
+ ]
175
+ else:
176
+ headers = ["Agent ID", "Tool Name", "Unique Identifier"]
177
+ data = [
178
+ (str(agent_id), str(tool_name), f"{agent_id}-{tool_name}")
179
+ for agent_id, tools in result["agent_tools_map"].items()
180
+ for tool_name in tools
181
+ ]
182
+
183
+ click.echo(tabulate(data, headers=headers, tablefmt="grid"))
184
+ except (KeyError, TypeError) as e:
185
+ click.echo(f"Error processing tool data: {str(e)}")
186
+ except json.JSONDecodeError as e:
187
+ click.echo(f"Error decoding JSON response: {str(e)}")
188
+ except IOError as e:
189
+ click.echo(f"Network or I/O error: {str(e)}")
190
+
191
+
192
+ @click.command(name="tool-description")
193
+ @click.argument("tool_id")
194
+ @click.option("--chain-config", default="gnosis", help="Chain configuration to use.")
195
+ def tool_description(tool_id: str, chain_config: str) -> None:
196
+ """Fetch and display the description of a specific tool."""
197
+ try:
198
+ description = get_tool_description(tool_id, chain_config)
199
+ click.echo(f"Description for tool {tool_id}: {description}")
200
+ except KeyError as e:
201
+ click.echo(f"Tool not found or missing description: {str(e)}")
202
+ except json.JSONDecodeError as e:
203
+ click.echo(f"Error decoding JSON response: {str(e)}")
204
+ except IOError as e:
205
+ click.echo(f"Network or I/O error: {str(e)}")
206
+
207
+
208
+ @click.command(name="tool-io-schema")
209
+ @click.argument("tool_id")
210
+ @click.option("--chain-config", default="gnosis", help="Chain configuration to use.")
211
+ def tool_io_schema(tool_id: str, chain_config: str) -> None:
212
+ """Fetch and display the input/output schema for a specific tool."""
213
+ try:
214
+ io_schema = get_tool_io_schema(tool_id, chain_config)
215
+ # Prepare data for tabulation
216
+ input_schema = [(key, io_schema["input"][key]) for key in io_schema["input"]]
217
+
218
+ # Handling nested output schema
219
+ output_schema = []
220
+ if "properties" in io_schema["output"]["schema"]:
221
+ for key, value in io_schema["output"]["schema"]["properties"].items():
222
+ output_schema.append((key, value["type"], value.get("description", "")))
223
+
224
+ # Display schemas in tabulated format
225
+ click.echo("Input Schema:")
226
+ click.echo(tabulate(input_schema, headers=["Field", "Value"], tablefmt="grid"))
227
+ click.echo("Output Schema:")
228
+ click.echo(
229
+ tabulate(
230
+ output_schema, headers=["Field", "Type", "Description"], tablefmt="grid"
231
+ )
232
+ )
233
+ except KeyError as e:
234
+ click.echo(f"Error accessing schema data: {str(e)}")
235
+ except json.JSONDecodeError as e:
236
+ click.echo(f"Error decoding JSON response: {str(e)}")
237
+ except IOError as e:
238
+ click.echo(f"Network or I/O error: {str(e)}")
239
+
240
+
151
241
  cli.add_command(interact)
152
242
  cli.add_command(prompt_to_ipfs)
153
243
  cli.add_command(push_to_ipfs)
154
244
  cli.add_command(to_png)
245
+ cli.add_command(tools_for_agents)
246
+ cli.add_command(tool_io_schema)
247
+ cli.add_command(tool_description)
155
248
 
156
249
 
157
250
  if __name__ == "__main__":
@@ -35,7 +35,7 @@ from dataclasses import asdict, dataclass
35
35
  from datetime import datetime
36
36
  from enum import Enum
37
37
  from pathlib import Path
38
- from typing import Any, Dict, List, Optional, Tuple
38
+ from typing import Any, Dict, List, Optional, Tuple, Union
39
39
 
40
40
  import requests
41
41
  import websocket
@@ -160,18 +160,10 @@ def get_mech_config(chain_config: Optional[str] = None) -> MechConfig:
160
160
  if chain_config is None:
161
161
  chain_config = next(iter(data))
162
162
 
163
- print("Chain configuration:")
164
163
  entry = data[chain_config].copy()
165
164
  ledger_config = LedgerConfig(**entry.pop("ledger_config"))
166
165
  mech_config = MechConfig(**entry, ledger_config=ledger_config)
167
166
 
168
- print(f" - Chain ID: {chain_config}")
169
- print(f" - Gas limit: {mech_config.gas_limit}")
170
- print(f" - Contract ABI URL: {mech_config.contract_abi_url}")
171
- print(f" - Transation URL: {mech_config.transaction_url}")
172
- print(f" - Subgraph URL: {mech_config.subgraph_url}")
173
- print("")
174
-
175
167
  return mech_config
176
168
 
177
169
 
@@ -303,12 +295,16 @@ def verify_or_retrieve_tool(
303
295
  :return: The result of the verification or retrieval.
304
296
  :rtype: str
305
297
  """
306
- available_tools = fetch_tools(
298
+ # Fetch tools, possibly including metadata
299
+ tools_data = fetch_tools(
307
300
  agent_id=agent_id,
308
301
  ledger_api=ledger_api,
309
302
  agent_registry_contract=agent_registry_contract,
310
303
  contract_abi_url=contract_abi_url,
304
+ include_metadata=False, # Ensure this is False to only get the list of tools
311
305
  )
306
+ # Ensure only the list of tools is used
307
+ available_tools = tools_data if isinstance(tools_data, list) else tools_data[0]
312
308
  if tool is not None and tool not in available_tools:
313
309
  raise ValueError(
314
310
  f"Provided tool `{tool}` not in the list of available tools; Available tools={available_tools}"
@@ -323,8 +319,9 @@ def fetch_tools(
323
319
  ledger_api: EthereumApi,
324
320
  agent_registry_contract: str,
325
321
  contract_abi_url: str,
326
- ) -> List[str]:
327
- """Fetch tools for specified agent ID."""
322
+ include_metadata: bool = False,
323
+ ) -> Union[List[str], Tuple[List[str], Dict[str, Any]]]:
324
+ """Fetch tools for specified agent ID, optionally include metadata."""
328
325
  mech_registry = get_contract(
329
326
  contract_address=agent_registry_contract,
330
327
  abi=get_abi(agent_registry_contract, contract_abi_url),
@@ -332,7 +329,12 @@ def fetch_tools(
332
329
  )
333
330
  token_uri = mech_registry.functions.tokenURI(agent_id).call()
334
331
  response = requests.get(token_uri).json()
335
- return response["tools"]
332
+ tools = response.get("tools", [])
333
+
334
+ if include_metadata:
335
+ tool_metadata = response.get("toolMetadata", {})
336
+ return tools, tool_metadata
337
+ return tools
336
338
 
337
339
 
338
340
  def send_request( # pylint: disable=too-many-arguments,too-many-locals
@@ -0,0 +1,181 @@
1
+ """Module for managing mechanical tools and their interactions with blockchain."""
2
+
3
+ import json
4
+ from dataclasses import asdict
5
+ from typing import Any, Dict, List, Optional, Tuple, Union
6
+
7
+ import requests
8
+ from aea_ledger_ethereum import EthereumApi
9
+
10
+ from mech_client.interact import fetch_tools, get_abi, get_contract, get_mech_config
11
+
12
+
13
+ def get_total_supply(chain_config: str = "gnosis") -> int:
14
+ """
15
+ Fetches the total supply of tokens from a contract using the chain configuration.
16
+
17
+ :param chain_config: The chain configuration to use.
18
+ :type chain_config: str
19
+ :return: The total supply of tokens.
20
+ :rtype: int
21
+ """
22
+ # Get the mech configuration
23
+ mech_config = get_mech_config(chain_config)
24
+ ledger_config = mech_config.ledger_config
25
+
26
+ # Setup Ethereum API
27
+ ledger_api = EthereumApi(**asdict(ledger_config))
28
+
29
+ # Fetch ABI and create contract instance
30
+ abi = get_abi(mech_config.agent_registry_contract, mech_config.contract_abi_url)
31
+ contract = get_contract(mech_config.agent_registry_contract, abi, ledger_api)
32
+
33
+ # Call the totalSupply function
34
+ return contract.functions.totalSupply().call()
35
+
36
+
37
+ def get_agent_tools(
38
+ agent_id: int, chain_config: str = "gnosis"
39
+ ) -> Optional[Union[List[str], Tuple[List[str], Dict[str, Any]]]]:
40
+ """
41
+ Fetch tools for a given agent ID.
42
+
43
+ :param agent_id: The ID of the agent.
44
+ :param chain_config: The chain configuration to use (default is "gnosis").
45
+ :return: A list of tools if successful, or a tuple of (list of tools, metadata) if metadata is included, or None if an error occurs.
46
+ """
47
+ try:
48
+ # Get the mech configuration
49
+ mech_config = get_mech_config(chain_config)
50
+ ledger_config = mech_config.ledger_config
51
+
52
+ # Setup Ethereum API
53
+ ledger_api = EthereumApi(**asdict(ledger_config))
54
+
55
+ # Fetch tools for the given agent ID
56
+ return fetch_tools(
57
+ agent_id=agent_id,
58
+ ledger_api=ledger_api,
59
+ agent_registry_contract=mech_config.agent_registry_contract,
60
+ contract_abi_url=mech_config.contract_abi_url,
61
+ )
62
+ except (requests.exceptions.RequestException, json.JSONDecodeError, KeyError) as e:
63
+ print(f"An error occurred while fetching tools for agent {agent_id}: {e}")
64
+ return None
65
+
66
+
67
+ def get_tools_for_agents(
68
+ agent_id: Optional[int] = None, chain_config: str = "gnosis"
69
+ ) -> Dict[str, Any]:
70
+ """
71
+ Retrieve tools for specified agents or all agents if no specific agent is provided.
72
+
73
+ :param agent_id: Optional; specific agent ID to fetch tools for.
74
+ :param chain_config: The chain configuration to use.
75
+ :return: Dictionary of tools with identifiers or a mapping of agent IDs to tools.
76
+ """
77
+ try:
78
+ total_supply = get_total_supply(chain_config)
79
+
80
+ if agent_id is not None:
81
+ tools = get_agent_tools(agent_id, chain_config)
82
+ if isinstance(tools, list):
83
+ tools_with_ids = [
84
+ {"tool_name": tool, "unique_identifier": f"{agent_id}-{tool}"}
85
+ for tool in tools
86
+ ]
87
+ else:
88
+ tools_with_ids = []
89
+ return {"agent_id": agent_id, "tools": tools_with_ids}
90
+
91
+ all_tools_with_ids = []
92
+ agent_tools_map = {}
93
+
94
+ for current_agent_id in range(1, total_supply + 1):
95
+ tools = get_agent_tools(current_agent_id, chain_config)
96
+ if isinstance(tools, list):
97
+ tools_with_ids = [
98
+ {
99
+ "tool_name": tool,
100
+ "unique_identifier": f"{current_agent_id}-{tool}",
101
+ }
102
+ for tool in tools
103
+ ]
104
+ agent_tools_map[current_agent_id] = tools
105
+ all_tools_with_ids.extend(tools_with_ids)
106
+
107
+ return {
108
+ "all_tools_with_identifiers": all_tools_with_ids,
109
+ "agent_tools_map": agent_tools_map,
110
+ }
111
+ except Exception as e:
112
+ print(f"Error in get_tools_for_agents: {str(e)}")
113
+ raise
114
+
115
+
116
+ def get_tool_description(unique_identifier: str, chain_config: str = "gnosis") -> str:
117
+ """
118
+ Fetch the description of a specific tool based on a unique identifier.
119
+
120
+ :param unique_identifier: The unique identifier for the tool.
121
+ :param chain_config: The chain configuration to use.
122
+ :return: Description of the tool or a default message if not available.
123
+ """
124
+ parts = unique_identifier.split("-")
125
+ agent_id = int(parts[0])
126
+ tool_name = "-".join(parts[1:])
127
+
128
+ # Get the mech configuration
129
+ mech_config = get_mech_config(chain_config)
130
+ ledger_api = EthereumApi(**asdict(mech_config.ledger_config))
131
+
132
+ tools_result = fetch_tools(
133
+ agent_id=agent_id,
134
+ ledger_api=ledger_api,
135
+ agent_registry_contract=mech_config.agent_registry_contract,
136
+ contract_abi_url=mech_config.contract_abi_url,
137
+ include_metadata=True,
138
+ )
139
+ if isinstance(tools_result, tuple) and len(tools_result) == 2:
140
+ _, tool_metadata = tools_result
141
+ tool_info = tool_metadata.get(tool_name, {})
142
+ if isinstance(tool_info, dict):
143
+ return tool_info.get("description", "Description not available")
144
+ return "Description not available"
145
+
146
+
147
+ def get_tool_io_schema(
148
+ unique_identifier: str, chain_config: str = "gnosis"
149
+ ) -> Dict[str, Any]:
150
+ """
151
+ Fetch the input and output schema of a specific tool based on a unique identifier.
152
+
153
+ :param unique_identifier: The unique identifier for the tool.
154
+ :param chain_config: The chain configuration to use.
155
+ :return: Dictionary containing input and output schemas.
156
+ """
157
+ parts = unique_identifier.split("-")
158
+ agent_id = int(parts[0])
159
+ tool_name = "-".join(parts[1:])
160
+
161
+ # Get the mech configuration
162
+ mech_config = get_mech_config(chain_config)
163
+ ledger_api = EthereumApi(**asdict(mech_config.ledger_config))
164
+
165
+ tools_result = fetch_tools(
166
+ agent_id=agent_id,
167
+ ledger_api=ledger_api,
168
+ agent_registry_contract=mech_config.agent_registry_contract,
169
+ contract_abi_url=mech_config.contract_abi_url,
170
+ include_metadata=True,
171
+ )
172
+ if isinstance(tools_result, tuple) and len(tools_result) == 2:
173
+ _, tool_metadata = tools_result
174
+ tool_info = tool_metadata.get(tool_name, {})
175
+ if isinstance(tool_info, dict):
176
+ return {
177
+ "input": tool_info.get("input", {}),
178
+ "output": tool_info.get("output", {}),
179
+ }
180
+
181
+ return {"input": {}, "output": {}}
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "mech-client"
3
- version = "0.2.15"
3
+ version = "0.2.16"
4
4
  description = "Basic client to interact with a mech"
5
5
  authors = ["David Minarsch <david.minarsch@googlemail.com>"]
6
6
  readme = "README.md"
@@ -33,6 +33,7 @@ open-aea-ledger-cosmos = "^1.53.0"
33
33
  gql = ">=3.4.1"
34
34
  asn1crypto = ">=1.4.0,<1.5.0"
35
35
  websocket-client = ">=0.32.0,<1"
36
+ tabulate = "^0.9.0"
36
37
 
37
38
  [tool.poetry.scripts]
38
39
  mechx = "mech_client.cli:cli"
@@ -1,3 +0,0 @@
1
- """Mech client."""
2
-
3
- __version__ = "0.2.15"
File without changes