langchain-trigger-server 0.1.15__tar.gz → 0.1.17__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 (17) hide show
  1. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/PKG-INFO +1 -1
  2. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/app.py +32 -4
  3. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/database/interface.py +10 -0
  4. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/database/supabase.py +27 -0
  5. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/pyproject.toml +1 -1
  6. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/.github/workflows/release.yml +0 -0
  7. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/.vscode/settings.json +0 -0
  8. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/README.md +0 -0
  9. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/__init__.py +0 -0
  10. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/core.py +0 -0
  11. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/cron_manager.py +0 -0
  12. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/database/__init__.py +0 -0
  13. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/decorators.py +0 -0
  14. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/triggers/__init__.py +0 -0
  15. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/langchain_triggers/triggers/cron_trigger.py +0 -0
  16. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/test_framework.py +0 -0
  17. {langchain_trigger_server-0.1.15 → langchain_trigger_server-0.1.17}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langchain-trigger-server
3
- Version: 0.1.15
3
+ Version: 0.1.17
4
4
  Summary: Generic event-driven triggers framework
5
5
  Project-URL: Homepage, https://github.com/langchain-ai/open-agent-platform
6
6
  Project-URL: Repository, https://github.com/langchain-ai/open-agent-platform
@@ -72,6 +72,9 @@ class TriggerServer:
72
72
  self,
73
73
  auth_handler: Callable,
74
74
  ):
75
+ # Configure uvicorn logging to use consistent formatting
76
+ self._configure_uvicorn_logging()
77
+
75
78
  self.app = FastAPI(
76
79
  title="Triggers Server",
77
80
  description="Event-driven triggers framework",
@@ -123,6 +126,31 @@ class TriggerServer:
123
126
  async def shutdown_event():
124
127
  await self.cron_manager.shutdown()
125
128
 
129
+ def _configure_uvicorn_logging(self) -> None:
130
+ """Configure uvicorn loggers to use consistent formatting for production deployments."""
131
+ formatter = logging.Formatter("%(levelname)s: %(name)s - %(message)s")
132
+
133
+ # Configure uvicorn access logger
134
+ uvicorn_access_logger = logging.getLogger("uvicorn.access")
135
+ uvicorn_access_logger.handlers.clear()
136
+ access_handler = logging.StreamHandler()
137
+ access_handler.setFormatter(formatter)
138
+ uvicorn_access_logger.addHandler(access_handler)
139
+
140
+ # Configure uvicorn error logger
141
+ uvicorn_error_logger = logging.getLogger("uvicorn.error")
142
+ uvicorn_error_logger.handlers.clear()
143
+ error_handler = logging.StreamHandler()
144
+ error_handler.setFormatter(formatter)
145
+ uvicorn_error_logger.addHandler(error_handler)
146
+
147
+ # Configure uvicorn main logger
148
+ uvicorn_logger = logging.getLogger("uvicorn")
149
+ uvicorn_logger.handlers.clear()
150
+ main_handler = logging.StreamHandler()
151
+ main_handler.setFormatter(formatter)
152
+ uvicorn_logger.addHandler(main_handler)
153
+
126
154
  def add_trigger(self, trigger: TriggerTemplate) -> None:
127
155
  """Add a trigger template to the app."""
128
156
  # Check for duplicate IDs
@@ -255,18 +283,18 @@ class TriggerServer:
255
283
  detail=f"Invalid payload for trigger: {str(e)}"
256
284
  )
257
285
 
258
- # Check for duplicate registration based on resource data
286
+ # Check for duplicate registration based on resource data within this user's scope
259
287
  resource_dict = registration_instance.model_dump()
260
- existing_registration = await self.database.find_registration_by_resource(
288
+ existing_registration = await self.database.find_user_registration_by_resource(
289
+ user_id=user_id,
261
290
  template_id=trigger.id,
262
291
  resource_data=resource_dict
263
292
  )
264
293
 
265
- # TODO(sam) figure out how to allow duplicates across users.....very unnatural constraint to have
266
294
  if existing_registration:
267
295
  raise HTTPException(
268
296
  status_code=400,
269
- detail=f"A registration with this configuration already exists for trigger type '{trigger.id}'. Registration ID: {existing_registration.get('id')}"
297
+ detail=f"You already have a registration with this configuration for trigger type '{trigger.id}'. Registration ID: {existing_registration.get('id')}"
270
298
  )
271
299
 
272
300
 
@@ -67,6 +67,16 @@ class TriggerDatabaseInterface(ABC):
67
67
  """Find trigger registration by matching resource data."""
68
68
  pass
69
69
 
70
+ @abstractmethod
71
+ async def find_user_registration_by_resource(
72
+ self,
73
+ user_id: str,
74
+ template_id: str,
75
+ resource_data: Dict[str, Any]
76
+ ) -> Optional[Dict[str, Any]]:
77
+ """Find trigger registration by matching resource data for a specific user."""
78
+ pass
79
+
70
80
  @abstractmethod
71
81
  async def get_all_registrations(self, template_id: str) -> List[Dict[str, Any]]:
72
82
  """Get all registrations for a specific trigger template."""
@@ -250,6 +250,33 @@ class SupabaseTriggerDatabase(TriggerDatabaseInterface):
250
250
  logger.error(f"Error finding registration by resource: {e}")
251
251
  return None
252
252
 
253
+ async def find_user_registration_by_resource(
254
+ self,
255
+ user_id: str,
256
+ template_id: str,
257
+ resource_data: Dict[str, Any]
258
+ ) -> Optional[Dict[str, Any]]:
259
+ """Find trigger registration by matching resource data for a specific user."""
260
+ try:
261
+ # Build query to match against trigger_registrations with template_id and user_id filter
262
+ query = self.client.table("trigger_registrations").select(
263
+ "*, trigger_templates(id, name, description)"
264
+ ).eq("trigger_templates.id", template_id).eq("user_id", user_id)
265
+
266
+ # Add resource field matches
267
+ for field, value in resource_data.items():
268
+ query = query.eq(f"resource->>{field}", value)
269
+
270
+ response = query.execute()
271
+
272
+ if response.data:
273
+ return response.data[0] # Return first match
274
+ return None
275
+
276
+ except Exception as e:
277
+ logger.error(f"Error finding user registration by resource: {e}")
278
+ return None
279
+
253
280
  async def get_all_registrations(self, template_id: str) -> List[Dict[str, Any]]:
254
281
  """Get all registrations for a specific trigger template."""
255
282
  try:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "langchain-trigger-server"
7
- version = "0.1.15"
7
+ version = "0.1.17"
8
8
  description = "Generic event-driven triggers framework"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"