agentstr 0.0.10__py3-none-any.whl → 0.1.8__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
agentstr/nostr.py CHANGED
@@ -1,53 +1,193 @@
1
+ import logging
1
2
  from typing import Optional
2
- from os import getenv
3
- import logging
4
3
 
5
- try:
4
+ try:
6
5
  import asyncio
7
6
  except ImportError:
8
- raise ImportError("`asyncio` not installed. Please install using `pip install asyncio`")
7
+ raise ImportError(
8
+ "`asyncio` not installed. Please install using `pip install asyncio`"
9
+ )
9
10
 
10
11
  try:
11
- from nostr_sdk import Keys, Client, EventBuilder, NostrSigner, SendEventOutput, Event, Metadata
12
+ from nostr_sdk import (
13
+ Client,
14
+ Coordinate,
15
+ Event,
16
+ EventBuilder,
17
+ EventId,
18
+ Keys,
19
+ Kind,
20
+ Metadata,
21
+ NostrSigner,
22
+ ProductData,
23
+ PublicKey,
24
+ ShippingCost,
25
+ ShippingMethod,
26
+ StallData,
27
+ Tag,
28
+ Timestamp,
29
+ )
30
+
12
31
  except ImportError:
13
- raise ImportError("`nostr_sdk` not installed. Please install using `pip install nostr_sdk`")
32
+ raise ImportError(
33
+ "`nostr_sdk` not installed. Please install using `pip install nostr_sdk`"
34
+ )
35
+
36
+
37
+ class NostrClient:
38
+ """
39
+ NostrClient implements the set of Nostr utilities required for higher level functions implementing
40
+ like the Marketplace.
41
+
42
+ Nostr is an asynchronous communication protocol. To hide this, NostrClient exposes synchronous functions.
43
+ Users of the NostrClient should ignore `_async_` functions which are for internal purposes only.
44
+ """
14
45
 
15
- class NostrClient():
16
-
17
46
  logger = logging.getLogger("NostrClient")
18
47
  ERROR: str = "ERROR"
19
48
  SUCCESS: str = "SUCCESS"
20
-
49
+
21
50
  def __init__(
22
51
  self,
23
- relay: str = None,
24
- nsec: str = None,
25
- ):
26
- """Initialize the Nostr client.
52
+ relay: str,
53
+ nsec: str,
54
+ ) -> None:
55
+ """
56
+ Initialize the Nostr client.
27
57
 
28
58
  Args:
29
- relay: Nostr relay that the client will connect to
59
+ relay: Nostr relay that the client will connect to
30
60
  nsec: Nostr private key in bech32 format
31
61
  """
32
62
  # Set log handling
33
63
  if not NostrClient.logger.hasHandlers():
34
64
  console_handler = logging.StreamHandler()
35
65
  console_handler.setLevel(logging.INFO)
36
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
66
+ formatter = logging.Formatter(
67
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
68
+ )
37
69
  console_handler.setFormatter(formatter)
38
70
  NostrClient.logger.addHandler(console_handler)
39
-
71
+
72
+ # configure relay and keys for the client
40
73
  self.relay = relay
41
74
  self.keys = Keys.parse(nsec)
42
75
  self.nostr_signer = NostrSigner.keys(self.keys)
43
76
  self.client = Client(self.nostr_signer)
44
-
45
77
 
46
- async def connect(
47
- self
48
- ) -> str:
49
-
50
- """Add relay to the NostrClient instance and connect to it.
78
+ def delete_event(self, event_id: EventId, reason: Optional[str] = None) -> EventId:
79
+ """
80
+ Requests the relay to delete an event. Relays may or may not honor the request.
81
+
82
+ Args:
83
+ event_id: EventId associated with the event to be deleted
84
+ reason: optional reason for deleting the event
85
+
86
+ Returns:
87
+ EventId: if of the event requesting the deletion of event_id
88
+
89
+ Raises:
90
+ RuntimeError: if the deletion event can't be published
91
+ """
92
+ event_builder = EventBuilder.delete(ids=[event_id], reason=reason)
93
+ # Run the async publishing function synchronously
94
+ return asyncio.run(self._async_publish_event(event_builder))
95
+
96
+ def publish_event(self, event_builder: EventBuilder) -> EventId:
97
+ """
98
+ Publish generic Nostr event to the relay
99
+
100
+ Returns:
101
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
102
+
103
+ Raises:
104
+ RuntimeError: if the product can't be published
105
+ """
106
+ # Run the async publishing function synchronously
107
+ return asyncio.run(self._async_publish_event(event_builder))
108
+
109
+ def publish_note(self, text: str) -> EventId:
110
+ """Publish note with event kind 1
111
+
112
+ Args:
113
+ text: text to be published as kind 1 event
114
+
115
+ Returns:
116
+ EventId: EventId if successful or NostrClient.ERROR if unsuccesful
117
+
118
+ Raises:
119
+ RuntimeError: if the product can't be published
120
+ """
121
+ # Run the async publishing function synchronously
122
+ return asyncio.run(self._async_publish_note(text))
123
+
124
+ def publish_product(self, product: ProductData) -> EventId:
125
+ """
126
+ Create or update a NIP-15 Marketplace product with event kind 30018
127
+
128
+ Args:
129
+ product: product to be published
130
+
131
+ Returns:
132
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
133
+
134
+ Raises:
135
+ RuntimeError: if the product can't be published
136
+ """
137
+ # Run the async publishing function synchronously
138
+ return asyncio.run(self._async_publish_product(product))
139
+
140
+ def publish_profile(self, name: str, about: str, picture: str) -> EventId:
141
+ """
142
+ Publish a Nostr profile with event kind 0
143
+
144
+ Args:
145
+ name: name of the Nostr profile
146
+ about: brief description about the profile
147
+ picture: url to a png file with a picture for the profile
148
+
149
+ Returns:
150
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
151
+
152
+ Raises:
153
+ RuntimeError: if the profile can't be published
154
+ """
155
+ # Run the async publishing function synchronously
156
+ return asyncio.run(self._async_publish_profile(name, about, picture))
157
+
158
+ def publish_stall(self, stall: StallData) -> EventId:
159
+ """Publish a stall to nostr
160
+
161
+ Args:
162
+ stall: stall to be published
163
+
164
+ Returns:
165
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
166
+ """
167
+ try:
168
+ return asyncio.run(self._async_publish_stall(stall))
169
+ except Exception as e:
170
+ self.logger.error(f"Failed to publish stall: {e}")
171
+ return NostrClient.ERROR
172
+
173
+ @classmethod
174
+ def set_logging_level(cls, logging_level: int) -> None:
175
+ """Set the logging level for the NostrClient logger.
176
+
177
+ Args:
178
+ logging_level: The logging level (e.g., logging.DEBUG, logging.INFO)
179
+ """
180
+ cls.logger.setLevel(logging_level)
181
+ for handler in cls.logger.handlers:
182
+ handler.setLevel(logging_level)
183
+ cls.logger.info(f"Logging level set to {logging.getLevelName(logging_level)}")
184
+
185
+ # ----------------------------------------------------------------------------------------------
186
+ # --*-- async functions for internal use only. Developers should use synchronous functions above
187
+ # ----------------------------------------------------------------------------------------------
188
+
189
+ async def _async_connect(self) -> str:
190
+ """Asynchronous function to add relay to the NostrClient instance and connect to it.
51
191
 
52
192
  Returns:
53
193
  str: NostrClient.SUCCESS or NostrClient.ERROR
@@ -59,83 +199,129 @@ class NostrClient():
59
199
  NostrClient.logger.info("Connected to relay.")
60
200
  return NostrClient.SUCCESS
61
201
  except Exception as e:
62
- NostrClient.logger.error(f"Unable to connect to relay {self.relay}. Exception: {e}.")
202
+ NostrClient.logger.error(
203
+ f"Unable to connect to relay {self.relay}. Exception: {e}."
204
+ )
63
205
  return NostrClient.ERROR
64
-
65
- async def publish_text_note(
66
- self,
67
- text: str
68
- ) -> str:
69
-
70
- """Publish kind 1 event (text note) to the relay
71
206
 
72
- Args:
73
- text: text to be published as kind 1 event
207
+ async def _async_publish_event(self, event_builder: EventBuilder) -> EventId:
208
+ """
209
+ Publish generic Nostr event to the relay
74
210
 
75
211
  Returns:
76
- str: event id if successful and "error" string if unsuccesful
212
+ EventId: event id of the published event
213
+
214
+ Raises:
215
+ RuntimeError: if the event can't be published
77
216
  """
78
- builder = EventBuilder.text_note(text)
217
+ connected = await self._async_connect()
218
+
219
+ if connected == NostrClient.ERROR:
220
+ raise RuntimeError("Unable to connect to the relay")
79
221
 
80
222
  try:
81
- output = await self.client.send_event_builder(builder)
82
- NostrClient.logger.info(f"Text note published with event id: {output.id.to_bech32()}")
83
- return output.id.to_bech32()
223
+ output = await self.client.send_event_builder(event_builder)
224
+ if len(output.success) > 0:
225
+ NostrClient.logger.info(
226
+ f"Event published with event id: {output.id.to_bech32()}"
227
+ )
228
+ return output.id
229
+ else:
230
+ raise RuntimeError("Unable to publish event")
84
231
  except Exception as e:
85
- NostrClient.logger.error(f"Unable to publish text note to relay {self.relay}. Exception: {e}.")
86
- return NostrClient.ERROR
232
+ NostrClient.logger.error(
233
+ f"NostrClient instance not properly initialized. Exception: {e}."
234
+ )
235
+ raise RuntimeError(
236
+ f"NostrClient instance not properly initialized. Exception: {e}."
237
+ )
87
238
 
88
- async def publish_event(
89
- self,
90
- builder: EventBuilder
91
- ) -> str:
92
-
93
- """Publish generic Nostr event to the relay
239
+ async def _async_publish_note(self, text: str) -> EventId:
240
+ """
241
+ Asynchronous funcion to publish kind 1 event (text note) to the relay
242
+
243
+ Args:
244
+ text: text to be published as kind 1 event
94
245
 
95
246
  Returns:
96
- str: event id if successful or "error" string if unsuccesful
247
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
248
+
249
+ Raises:
250
+ RuntimeError: if the event can't be published
97
251
  """
98
- try:
99
- output = await self.client.send_event_builder(builder)
100
- NostrClient.logger.info(f"Event published with event id: {output.id.to_bech32()}")
101
- return output.id.to_bech32()
102
- except Exception as e:
103
- NostrClient.logger.error(f"Unable to publish event to relay {self.relay}. Exception: {e}.")
104
- return NostrClient.ERROR
105
-
106
- async def publish_profile(self, name: str, about: str, picture: str) -> str:
107
- """Publish a Nostr profile.
252
+ event_builder = EventBuilder.text_note(text)
253
+ return await self._async_publish_event(event_builder)
254
+
255
+ async def _async_publish_product(self, product: ProductData) -> EventId:
256
+ """
257
+ Asynchronous function to create or update a NIP-15 Marketplace product with event kind 30018
258
+
259
+ Args:
260
+ product: product to publish
261
+
262
+ Returns:
263
+ EventId: event id if successful or NostrClient.ERROR if unsuccesfull
264
+
265
+ Raises:
266
+ RuntimeError: if the product can't be published
267
+ """
268
+ coordinate_tag = Coordinate(
269
+ Kind(30017), self.keys.public_key(), product.stall_id
270
+ )
271
+
272
+ # EventBuilder.product_data() has a bug with tag handling.
273
+ # We use the function to create the content field and discard the eventbuilder
274
+ bad_event_builder = EventBuilder.product_data(product)
275
+
276
+ # create an event from bad_event_builder to extract the content - not broadcasted
277
+ bad_event = await self.client.sign_event_builder(bad_event_builder)
278
+ content = bad_event.content()
279
+
280
+ # build a new event with the right tags and the content
281
+ good_event_builder = EventBuilder(Kind(30018), content).tags(
282
+ [Tag.identifier(product.id), Tag.coordinate(coordinate_tag)]
283
+ )
284
+ self.logger.info("Product event: " + str(good_event_builder))
285
+ return await self._async_publish_event(good_event_builder)
286
+
287
+ async def _async_publish_profile(
288
+ self, name: str, about: str, picture: str
289
+ ) -> EventId:
290
+ """
291
+ Asynchronous function to publish a Nostr profile with event kind 0
108
292
 
109
293
  Args:
110
294
  name: name of the Nostr profile
111
295
  about: brief description about the profile
112
296
  picture: url to a png file with a picture for the profile
113
-
297
+
114
298
  Returns:
115
- str: event id if successful or "error" string if unsuccesful
299
+ EventId: event id if successful or NostrClient.ERROR if unsuccesful
300
+
301
+ Raises:
302
+ RuntimeError: if the profile can't be published
116
303
  """
117
304
  metadata_content = Metadata().set_name(name)
118
305
  metadata_content = metadata_content.set_about(about)
119
306
  metadata_content = metadata_content.set_picture(picture)
120
307
 
121
- builder = EventBuilder.metadata(metadata_content)
122
- try:
123
- output = await self.client.send_event_builder(builder)
124
- NostrClient.logger.info(f"Profile note published with event id: {output.id.to_bech32()}")
125
- return output.id.to_bech32()
126
- except Exception as e:
127
- NostrClient.logger.error(f"Unable to publish profile to relay {self.relay}. Exception: {e}.")
128
- return NostrClient.ERROR
308
+ event_builder = EventBuilder.metadata(metadata_content)
309
+ return await self._async_publish_event(event_builder)
129
310
 
130
- @classmethod
131
- def set_logging_level(cls, logging_level: int):
311
+ async def _async_publish_stall(self, stall: StallData) -> EventId:
132
312
  """
133
- Set the logging level for the NostrClient logger.
313
+ Asynchronous function to create or update a NIP-15 Marketplace stall with event kind 30017
134
314
 
135
315
  Args:
136
- logging_level (int): The logging level (e.g., logging.DEBUG, logging.INFO).
316
+ stall: stall to be published
317
+
318
+ Returns:
319
+ EventId: event id if successful or NostrClient.ERROR if unsuccesfull
320
+
321
+ Raises:
322
+ RuntimeError: if the profile can't be published
137
323
  """
138
- cls.logger.setLevel(logging_level)
139
- for handler in cls.logger.handlers:
140
- handler.setLevel(logging_level)
141
- cls.logger.info(f"Logging level set to {logging.getLevelName(logging_level)}")
324
+
325
+ self.logger.info(f"Stall: {stall}")
326
+ event_builder = EventBuilder.stall_data(stall)
327
+ return await self._async_publish_event(event_builder)
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Synvya
3
+ Copyright (c) 2025 Synvya
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.2
2
+ Name: agentstr
3
+ Version: 0.1.8
4
+ Summary: Nostr extension for Phidata AI agents
5
+ Project-URL: Homepage, https://github.com/synvya/agentstr
6
+ Project-URL: Documentation, https://github.com/synvya/agentstr#readme
7
+ Project-URL: BugTracker, https://github.com/synvya/agentstr/issues
8
+ Requires-Python: <3.13,>=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: phidata>=2.7.0
12
+ Requires-Dist: openai>=1.50.0
13
+ Requires-Dist: packaging>=24.0
14
+ Requires-Dist: nostr-sdk>=0.38.0
15
+ Requires-Dist: pydantic>=2.0.0
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=7.0; extra == "dev"
18
+ Requires-Dist: black>=23.0; extra == "dev"
19
+ Requires-Dist: isort>=5.0; extra == "dev"
20
+ Requires-Dist: mypy>=1.0; extra == "dev"
21
+ Requires-Dist: python-dotenv>=1.0; extra == "dev"
22
+
23
+ # AgentStr
24
+
25
+ AgentStr is an extension of [Phidata](https://www.phidata.com) AI agents that enables peer-to-peer agent communication using the Nostr protocol.
26
+
27
+ ## Overview
28
+
29
+ AgentStr allows AI agents operated by different organizations to communicate and collaborate. For example:
30
+ - Agent A from Company A can coordinate with Agent B from Company B to execute a transaction
31
+ - Agents can discover and interact with each other through the decentralized Nostr network
32
+ - No central authority or intermediary required
33
+
34
+ ## Project Structure
35
+
36
+ ```
37
+ agentstr/
38
+ ├── src/ # Source code
39
+ │ └── agentstr/
40
+ │ ├── __init__.py
41
+ │ ├── marketplace.py
42
+ │ └── nostr.py
43
+ ├── tests/ # Test files
44
+ ├── docs/ # Documentation
45
+ ├── examples/ # Example implementations
46
+ └── ...
47
+ ```
48
+
49
+ ## Features
50
+
51
+ ### Current Features
52
+ - Create Merchant agents with Nostr identities
53
+ - Publish and manage merchant products using [NIP-15](https://github.com/nostr-protocol/nips/blob/master/15.md) marketplace protocol
54
+ - Create merchant stalls to organize products
55
+ - Handle shipping zones and costs
56
+ - Secure communication using Nostr keys
57
+
58
+ ### Roadmap
59
+ - [ ] Create marketplace with stalls
60
+ - [ ] Create Buyer agents
61
+ - [ ] Enable merchants to define products
62
+ - [ ] Add customer toolkit for buyers
63
+ - [ ] Support additional Nostr NIPs
64
+ - [ ] Add more agent interaction patterns
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ # Create a new python environment
70
+ python3 -m venv ~/.venvs/aienv
71
+ source ~/.venvs/aienv/bin/activate
72
+
73
+ # Install agentstr
74
+ pip install --upgrade pip
75
+ pip install agentstr
76
+ ```
77
+
78
+ ## Examples
79
+
80
+ See our [examples directory](examples/) for complete working implementations:
81
+
82
+ - [Basic CLI Agent](examples/basic_cli/main.py) - A complete example showing:
83
+ - Setting up merchant profiles
84
+ - Creating stalls with shipping methods
85
+ - Defining products with shipping costs
86
+ - Configuring the agent with the merchant toolkit
87
+ - Running an interactive CLI application
88
+
89
+
90
+ ## Documentation
91
+
92
+ For more detailed documentation and examples, see [Docs](docs/docs.md)
93
+
94
+ ## Development
95
+
96
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for:
97
+ - Development setup
98
+ - Testing instructions
99
+ - Contribution guidelines
100
+
101
+ ## License
102
+
103
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
104
+
105
+ ## Acknowledgments
106
+
107
+ - [Phidata](https://www.phidata.com) - For their AI agent framework
108
+ - [Rust-Nostr](https://rust-nostr.org) - For their Python Nostr SDK
109
+ - [Nostr Protocol](https://github.com/nostr-protocol/nips) - For the protocol specification
110
+
@@ -0,0 +1,8 @@
1
+ agentstr/__init__.py,sha256=bPXCN4fDtqII9UtDCwhWhkR6bi1LR4w0rR0vGeKPNoI,567
2
+ agentstr/marketplace.py,sha256=CavX0WQaCiz1sQhVs-PaHZ4YYUdcabW5V5eXrhtbT5A,40406
3
+ agentstr/nostr.py,sha256=PId6477VuShPq7nKgansgyJhJNNy9S8ycCf_3niizg4,11242
4
+ agentstr-0.1.8.dist-info/LICENSE,sha256=20H0yoEDN5XO1xPXyZCyJjvSTP0YiarRMKWPfiaBhQY,1063
5
+ agentstr-0.1.8.dist-info/METADATA,sha256=iHwN1hOoezYlYtYLAETT1evku9GAOzWthol7K7roYfs,3376
6
+ agentstr-0.1.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
7
+ agentstr-0.1.8.dist-info/top_level.txt,sha256=KZObFRHppZvKUGYB_m9w5HhLwps7jj7w6Xrw73dH2ss,9
8
+ agentstr-0.1.8.dist-info/RECORD,,
@@ -1,111 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: agentstr
3
- Version: 0.0.10
4
- Summary: A library for collaborative AI agents
5
- Author-email: Alejandro Gil <info@synvya.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/synvya/agentstr
8
- Project-URL: Documentation, https://github.com/synvya/agentstr#readme
9
- Project-URL: BugTracker, https://github.com/synvya/agentstr/issues
10
- Keywords: AI,agents,collaboration,library
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Operating System :: OS Independent
14
- Requires-Python: <3.13,>=3.9
15
- Description-Content-Type: text/markdown
16
- License-File: LICENSE
17
- Requires-Dist: phidata>=2.7.0
18
- Requires-Dist: openai>=1.50.0
19
- Requires-Dist: packaging>=24.0
20
- Requires-Dist: nostr-sdk>=0.38.0
21
-
22
- AgentStr
23
- ========
24
- AgentStr is an extension of [Phidata](https://www.phidata.com) AI agents that allows for agents to communicate with other agents in separate computers using the Nostr communication protocol.
25
-
26
- The goal is for Agent A operated by Company A to be able to work with Agent B operated by Company B to achieve a common goal. For example: Company A wants to buy a product sold by Company B so Agent A and Agent B can coordinate and execute the transaction.
27
-
28
- The basic communication tools are implemented in `agentstr/nostr.py`.
29
-
30
- As a first example, AgentStr provides the tools to create and operate a marketplace using the [NIP-15](https://github.com/nostr-protocol/nips/blob/master/15.md) Nostr Marketplace as its foundation. The file `agentstr/marketplace.py` includes NIP-15 `merchant` and `customer` profiles implemented each as a Phidata Toolkit.
31
-
32
- # License
33
- This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
34
-
35
- # Current status
36
- The library is in its infancy.
37
-
38
- Done:
39
- - Workflow to package and distribute the library
40
- - Users can create a Merchant profile and create an agent with the `merchant` toolkit that acts on behalf of the Merchant profile
41
-
42
-
43
- To be done:
44
- - Create a `marketplace` with `stalls`
45
- - Merchants to define `products`
46
- - Create a `customer` Toolkit
47
-
48
- # Installation
49
- AgentStr is offered as a python library available at https://pypi.org/project/agentstr/.
50
-
51
- Here is an example on how to use the library:
52
-
53
- 1. Create a new python environment for your app
54
- ```
55
- cd ~/
56
- python3 -m venv ~/.venvs/aienv
57
- source ~/.venvs/aienv/bin/activate
58
- ```
59
- 2. Install the agentstr library
60
- ```
61
- pip install --upgrade pip
62
- pip install agentstr
63
- mkdir ~/mysampleapp
64
- cd ~/mysampleapp
65
- ```
66
- 3. Create a new python file
67
- ```
68
- touch main.py
69
- ```
70
- 4. Copy paste this code to the main.py file
71
- ```
72
- from dotenv import load_dotenv
73
- from os import getenv
74
- from phi.agent import Agent
75
- from phi.model.openai import OpenAIChat
76
- from agentstr.marketplace import MerchantProfile, Merchant
77
-
78
-
79
- profile = MerchantProfile(
80
- "Synvya",
81
- "Testing stuff",
82
- "https://i.nostr.build/ocjZ5GlAKwrvgRhx.png",
83
- getenv("NSEC_KEY")
84
- )
85
-
86
- agent = Agent(
87
- name="Merchant Assistant",
88
- model=OpenAIChat(id="gpt-4o"),
89
- tools=[Merchant(merchant_profile=profile, relay="wss://relay.damus.io")],
90
- show_tool_calls=True,
91
- markdown=True,
92
- debug_mode=True
93
- )
94
-
95
- agent.print_response("Publish the merchant information and tell me the event id used")
96
- ```
97
- 5. Export your OpenAI key and optionally a Nostr private key before running the code
98
- ```
99
- export OPENAI_API_KEY="sk-***"
100
- export NSEC_KEY="nsec***"
101
- python main.py
102
- ```
103
-
104
- This example will attempt to load a Nostr private key defined as NSEC_KEY in bech32 format. If a private key is not provided, the `MerchantProfile` class initializer will assign it a new one.
105
-
106
- # Contributing
107
- Refer to [CONTRIBUTING.md](CONTRIBUTING.md) for specific instructions on installation instructions for developers and how to contribute.
108
-
109
- # Acknowledgments
110
- - [Phidata](https://www.phidata.com) - For building robust AI agents.
111
- - [Rust-Nostr](https://rust-nostr.org/index.html) - For providing a python based Nostr SDK.
@@ -1,8 +0,0 @@
1
- agentstr/__init__.py,sha256=sXLh7g3KC4QCFxcZGBTpG2scR7hmmBsMjq6LqRptkRg,22
2
- agentstr/marketplace.py,sha256=XYF2ZrF6MpmxgCEOz3uN436cj7F4VHyUATFk8gmr7Zg,5245
3
- agentstr/nostr.py,sha256=C5zMWKBbXLkarZxBoTydJCZVzqGoCogBd_9v8Gll0VU,5012
4
- agentstr-0.0.10.dist-info/LICENSE,sha256=xF8akIKB07gOtkhjENT0xVbWGdFp4-srDKpZKjD03Js,1063
5
- agentstr-0.0.10.dist-info/METADATA,sha256=GuVKTLwjr6Skj4HH387GQP7YYMnTKulqgh8OQuuJGvs,4082
6
- agentstr-0.0.10.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
7
- agentstr-0.0.10.dist-info/top_level.txt,sha256=KZObFRHppZvKUGYB_m9w5HhLwps7jj7w6Xrw73dH2ss,9
8
- agentstr-0.0.10.dist-info/RECORD,,