mech-client 0.2.14__py3-none-any.whl → 0.2.16__py3-none-any.whl

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.
mech_client/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Mech client."""
2
2
 
3
- __version__ = "0.2.14"
3
+ __version__ = "0.2.16"
mech_client/cli.py CHANGED
@@ -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__":
mech_client/interact.py CHANGED
@@ -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,10 +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(f"Chain configuration: {chain_config}")
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)
166
+
167
167
  return mech_config
168
168
 
169
169
 
@@ -295,12 +295,16 @@ def verify_or_retrieve_tool(
295
295
  :return: The result of the verification or retrieval.
296
296
  :rtype: str
297
297
  """
298
- available_tools = fetch_tools(
298
+ # Fetch tools, possibly including metadata
299
+ tools_data = fetch_tools(
299
300
  agent_id=agent_id,
300
301
  ledger_api=ledger_api,
301
302
  agent_registry_contract=agent_registry_contract,
302
303
  contract_abi_url=contract_abi_url,
304
+ include_metadata=False, # Ensure this is False to only get the list of tools
303
305
  )
306
+ # Ensure only the list of tools is used
307
+ available_tools = tools_data if isinstance(tools_data, list) else tools_data[0]
304
308
  if tool is not None and tool not in available_tools:
305
309
  raise ValueError(
306
310
  f"Provided tool `{tool}` not in the list of available tools; Available tools={available_tools}"
@@ -315,8 +319,9 @@ def fetch_tools(
315
319
  ledger_api: EthereumApi,
316
320
  agent_registry_contract: str,
317
321
  contract_abi_url: str,
318
- ) -> List[str]:
319
- """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."""
320
325
  mech_registry = get_contract(
321
326
  contract_address=agent_registry_contract,
322
327
  abi=get_abi(agent_registry_contract, contract_abi_url),
@@ -324,7 +329,12 @@ def fetch_tools(
324
329
  )
325
330
  token_uri = mech_registry.functions.tokenURI(agent_id).call()
326
331
  response = requests.get(token_uri).json()
327
- 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
328
338
 
329
339
 
330
340
  def send_request( # pylint: disable=too-many-arguments,too-many-locals
@@ -371,7 +381,9 @@ def send_request( # pylint: disable=too-many-arguments,too-many-locals
371
381
  v1_file_hash_hex_truncated, v1_file_hash_hex = push_metadata_to_ipfs(
372
382
  prompt, tool, extra_attributes
373
383
  )
374
- print(f"Prompt uploaded: https://gateway.autonolas.tech/ipfs/{v1_file_hash_hex}")
384
+ print(
385
+ f" - Prompt uploaded: https://gateway.autonolas.tech/ipfs/{v1_file_hash_hex}"
386
+ )
375
387
  method_name = "request"
376
388
  methord_args = {"data": v1_file_hash_hex_truncated}
377
389
  tx_args = {
@@ -573,7 +585,7 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
573
585
  request_signature=request_event_signature,
574
586
  deliver_signature=deliver_event_signature,
575
587
  )
576
- print("Sending request...")
588
+ print("Sending Mech request...")
577
589
  transaction_digest = send_request(
578
590
  crypto=crypto,
579
591
  ledger_api=ledger_api,
@@ -586,19 +598,26 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
586
598
  timeout=timeout,
587
599
  sleep=sleep,
588
600
  )
601
+
602
+ if not transaction_digest:
603
+ print("Unable to send request")
604
+ return None
605
+
589
606
  transaction_url_formatted = mech_config.transaction_url.format(
590
607
  transaction_digest=transaction_digest
591
608
  )
592
- print(f"Transaction sent: {transaction_url_formatted}")
593
- print("Waiting for transaction receipt...")
609
+ print(f" - Transaction sent: {transaction_url_formatted}")
610
+ print(" - Waiting for transaction receipt...")
594
611
  request_id = watch_for_request_id(
595
612
  wss=wss,
596
613
  mech_contract=mech_contract,
597
614
  ledger_api=ledger_api,
598
615
  request_signature=request_event_signature,
599
616
  )
600
- print(f"Created on-chain request with ID {request_id}")
601
- print("Waiting for Mech response...")
617
+ print(f" - Created on-chain request with ID {request_id}")
618
+ print("")
619
+
620
+ print("Waiting for Mech deliver...")
602
621
  data_url = wait_for_data_url(
603
622
  request_id=request_id,
604
623
  wss=wss,
@@ -610,8 +629,9 @@ def interact( # pylint: disable=too-many-arguments,too-many-locals
610
629
  confirmation_type=confirmation_type,
611
630
  )
612
631
  if data_url:
613
- print(f"Data arrived: {data_url}")
614
- data = requests.get(f"{data_url}/{request_id}").json()
615
- print(f"Data from agent: {data}")
632
+ print(f" - Data arrived: {data_url}")
633
+ data = requests.get(f"{data_url}/{request_id}", timeout=30).json()
634
+ print(" - Data from agent:")
635
+ print(json.dumps(data, indent=2))
616
636
  return data
617
637
  return None
@@ -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
  Metadata-Version: 2.1
2
2
  Name: mech-client
3
- Version: 0.2.14
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:
@@ -1,6 +1,6 @@
1
- mech_client/__init__.py,sha256=UEdYXlGB0zRn_ifncW6eJqmz4ALKRS_Hzb-1QDeDuAg,43
1
+ mech_client/__init__.py,sha256=82jc8W2nwk575i4bZvj6qpAoJEn_97PMQSlAM7ma8u0,43
2
2
  mech_client/acn.py,sha256=Rj_jLPvJ5loDQfGbu3a_O24cJC4SwIErLceSz_zVYS8,5356
3
- mech_client/cli.py,sha256=QnC3Z_vth__ZiU12chRl8q5LYDLjyjzaofB41mWlq8c,4608
3
+ mech_client/cli.py,sha256=87ZBQAbzWpuf6s59FnBa4YO2eyDCyTOG22V54408MiY,8377
4
4
  mech_client/configs/mechs.json,sha256=IABnne1lWi62l84Hzqh3XrP659uPKme2k32yAI0HBrg,4488
5
5
  mech_client/helpers/__init__.py,sha256=f13zpwGDaKQUjML-5Iq66rRfzg8IS5UNK5I8gBr7w54,1028
6
6
  mech_client/helpers/acn/README.md,sha256=WMXR2Lk0IpWjr3vpZ8cxcTHk4gwsx4wC06UPkwj9dbQ,1641
@@ -30,14 +30,15 @@ mech_client/helpers/p2p_libp2p_client/README.md,sha256=6x9s6P7TdKkcvAS1wMFHXRz4a
30
30
  mech_client/helpers/p2p_libp2p_client/__init__.py,sha256=-GOP3D_JnmXTDomrMLCbnRk7vRQmihIqTYvyIPzx-q4,879
31
31
  mech_client/helpers/p2p_libp2p_client/connection.py,sha256=pvfHtI-NhgDbay1wLNit6m8InH4c0p00c3hQo0I2jwQ,27887
32
32
  mech_client/helpers/p2p_libp2p_client/connection.yaml,sha256=giYV5FwwugD7ha9IqFHJtvs-Oz1jC5og9rpkstrTqoc,1763
33
- mech_client/interact.py,sha256=E9AW_gRMkz8fRDeQSl9Dd97X_405GodA8Xylv5ZavzQ,20189
33
+ mech_client/interact.py,sha256=DOlUQBrfJKdDlfPnQ10tC8uAFTjlC3FGHOkPI2E_BYg,20846
34
+ mech_client/mech_tool_management.py,sha256=_nOa8FLaow2XyztxnEMT9sJSlZEhUidmG8dFdR1lfV8,6550
34
35
  mech_client/prompt_to_ipfs.py,sha256=XqSIBko15MEkpWOQNT97fRI6jNxMF5EDBDEPOJFdhyk,2533
35
36
  mech_client/push_to_ipfs.py,sha256=IfvgaPU79N_ZmCPF9d7sPCYz2uduZH0KjT_HQ2LHXoQ,2059
36
37
  mech_client/subgraph.py,sha256=4vY6QFyUVs15gS0SvanJbvAxb3aie07IuxQnfMMnStc,4931
37
38
  mech_client/to_png.py,sha256=pjUcFJ63MJj_r73eqnfqCWMtlpsrj6H4ZmgvIEmRcFw,2581
38
39
  mech_client/wss.py,sha256=hRInQjjsyOrs8dmgBb2VpJvpNt6Tx0aEiY3OhOPQvIs,6600
39
- mech_client-0.2.14.dist-info/LICENSE,sha256=mdBDB-mWKV5Cz4ejBzBiKqan6Z8zVLAh9xwM64O2FW4,11339
40
- mech_client-0.2.14.dist-info/METADATA,sha256=6my3h_RVRKV97PAPvCNxrgsE00zkXfAXfhVw1G2ugdg,10572
41
- mech_client-0.2.14.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
42
- mech_client-0.2.14.dist-info/entry_points.txt,sha256=SbRMRsayzD8XfNXhgwPuXEqQsdZ5Bw9XDPnUuaDExyY,45
43
- mech_client-0.2.14.dist-info/RECORD,,
40
+ mech_client-0.2.16.dist-info/LICENSE,sha256=mdBDB-mWKV5Cz4ejBzBiKqan6Z8zVLAh9xwM64O2FW4,11339
41
+ mech_client-0.2.16.dist-info/METADATA,sha256=RKWiEjr5xeovuc4sIDI633vmOd4M7oBStQdzjoSBPB0,17358
42
+ mech_client-0.2.16.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
43
+ mech_client-0.2.16.dist-info/entry_points.txt,sha256=SbRMRsayzD8XfNXhgwPuXEqQsdZ5Bw9XDPnUuaDExyY,45
44
+ mech_client-0.2.16.dist-info/RECORD,,