flock-core 0.4.523__py3-none-any.whl → 0.4.524__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.
Potentially problematic release.
This version of flock-core might be problematic. Click here for more details.
- flock/webapp/app/services/sharing_store.py +123 -104
- {flock_core-0.4.523.dist-info → flock_core-0.4.524.dist-info}/METADATA +1 -1
- {flock_core-0.4.523.dist-info → flock_core-0.4.524.dist-info}/RECORD +6 -6
- {flock_core-0.4.523.dist-info → flock_core-0.4.524.dist-info}/WHEEL +0 -0
- {flock_core-0.4.523.dist-info → flock_core-0.4.524.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.523.dist-info → flock_core-0.4.524.dist-info}/licenses/LICENSE +0 -0
|
@@ -227,136 +227,155 @@ class SQLiteSharedLinkStore(SharedLinkStoreInterface):
|
|
|
227
227
|
except sqlite3.Error as e:
|
|
228
228
|
logger.error(f"SQLite error saving feedback {record.feedback_id}: {e}", exc_info=True)
|
|
229
229
|
raise
|
|
230
|
+
# flock/webapp/app/services/sharing_store.py ← replace only this class
|
|
231
|
+
|
|
232
|
+
# ---------------------------------------------------------------------------
|
|
233
|
+
# Azure Table + Blob implementation
|
|
234
|
+
# ---------------------------------------------------------------------------
|
|
235
|
+
|
|
236
|
+
try:
|
|
237
|
+
from azure.storage.blob.aio import BlobServiceClient
|
|
238
|
+
AZURE_BLOB_AVAILABLE = True
|
|
239
|
+
except ImportError: # blob SDK not installed
|
|
240
|
+
AZURE_BLOB_AVAILABLE = False
|
|
241
|
+
BlobServiceClient = None
|
|
230
242
|
|
|
231
243
|
class AzureTableSharedLinkStore(SharedLinkStoreInterface):
|
|
232
|
-
"""Azure Table
|
|
244
|
+
"""Store configs in Azure Table; store large flock YAML in Blob Storage."""
|
|
245
|
+
|
|
246
|
+
_TABLE_NAME = "flocksharedlinks"
|
|
247
|
+
_FEEDBACK_TBL_NAME = "flockfeedback"
|
|
248
|
+
_CONTAINER_NAME = "flocksharedlinkdefs" # blobs live here
|
|
249
|
+
_PARTITION_KEY = "shared_links"
|
|
233
250
|
|
|
234
251
|
def __init__(self, connection_string: str):
|
|
235
|
-
"""Initialize Azure Table Storage store with connection string."""
|
|
236
252
|
if not AZURE_AVAILABLE:
|
|
237
|
-
raise ImportError("
|
|
253
|
+
raise ImportError("pip install azure-data-tables")
|
|
254
|
+
if not AZURE_BLOB_AVAILABLE:
|
|
255
|
+
raise ImportError("pip install azure-storage-blob")
|
|
238
256
|
|
|
239
257
|
self.connection_string = connection_string
|
|
240
|
-
self.
|
|
241
|
-
self.
|
|
242
|
-
self.feedback_table_name = "flockfeedback"
|
|
243
|
-
logger.info("AzureTableSharedLinkStore initialized")
|
|
258
|
+
self.table_svc = TableServiceClient.from_connection_string(connection_string)
|
|
259
|
+
self.blob_svc = BlobServiceClient.from_connection_string(connection_string)
|
|
244
260
|
|
|
261
|
+
# ------------------------------------------------------------------ init
|
|
245
262
|
async def initialize(self) -> None:
|
|
246
|
-
|
|
263
|
+
# 1. Azure Tables ----------------------------------------------------
|
|
247
264
|
try:
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
except ResourceExistsError:
|
|
253
|
-
logger.debug(f"Azure Table already exists: {self.shared_links_table_name}")
|
|
254
|
-
|
|
255
|
-
# Create feedback table
|
|
256
|
-
try:
|
|
257
|
-
await self.table_service_client.create_table(self.feedback_table_name)
|
|
258
|
-
logger.info(f"Created Azure Table: {self.feedback_table_name}")
|
|
259
|
-
except ResourceExistsError:
|
|
260
|
-
logger.debug(f"Azure Table already exists: {self.feedback_table_name}")
|
|
261
|
-
|
|
262
|
-
logger.info("Azure Table Storage initialized successfully")
|
|
263
|
-
except Exception as e:
|
|
264
|
-
logger.error(f"Error initializing Azure Table Storage: {e}", exc_info=True)
|
|
265
|
-
raise
|
|
265
|
+
await self.table_svc.create_table(self._TABLE_NAME)
|
|
266
|
+
logger.info("Created Azure Table '%s'", self._TABLE_NAME)
|
|
267
|
+
except ResourceExistsError:
|
|
268
|
+
logger.debug("Azure Table '%s' already exists", self._TABLE_NAME)
|
|
266
269
|
|
|
267
|
-
async def save_config(self, config: SharedLinkConfig) -> SharedLinkConfig:
|
|
268
|
-
"""Saves a shared link configuration to Azure Table Storage."""
|
|
269
270
|
try:
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
"chat_history_key": config.chat_history_key,
|
|
282
|
-
"chat_response_key": config.chat_response_key,
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
await table_client.upsert_entity(entity)
|
|
286
|
-
logger.info(f"Saved shared link config to Azure Table Storage for ID: {config.share_id} with type: {config.share_type}")
|
|
287
|
-
return config
|
|
288
|
-
except Exception as e:
|
|
289
|
-
logger.error(f"Error saving config to Azure Table Storage for ID {config.share_id}: {e}", exc_info=True)
|
|
290
|
-
raise
|
|
271
|
+
await self.table_svc.create_table(self._FEEDBACK_TBL_NAME)
|
|
272
|
+
logger.info("Created Azure Table '%s'", self._FEEDBACK_TBL_NAME)
|
|
273
|
+
except ResourceExistsError:
|
|
274
|
+
logger.debug("Azure Table '%s' already exists", self._FEEDBACK_TBL_NAME)
|
|
275
|
+
|
|
276
|
+
# 2. Blob container --------------------------------------------------
|
|
277
|
+
try:
|
|
278
|
+
await self.blob_svc.create_container(self._CONTAINER_NAME)
|
|
279
|
+
logger.info("Created Blob container '%s'", self._CONTAINER_NAME)
|
|
280
|
+
except ResourceExistsError:
|
|
281
|
+
logger.debug("Blob container '%s' already exists", self._CONTAINER_NAME)
|
|
291
282
|
|
|
283
|
+
# ------------------------------------------------------------- save_config
|
|
284
|
+
async def save_config(self, config: SharedLinkConfig) -> SharedLinkConfig:
|
|
285
|
+
"""Upload YAML to Blob, then upsert table row containing the blob name."""
|
|
286
|
+
blob_name = f"{config.share_id}.yaml"
|
|
287
|
+
blob_client = self.blob_svc.get_blob_client(self._CONTAINER_NAME, blob_name)
|
|
288
|
+
|
|
289
|
+
# 1. Upload flock_definition (overwrite in case of retry)
|
|
290
|
+
await blob_client.upload_blob(config.flock_definition,
|
|
291
|
+
overwrite=True,
|
|
292
|
+
content_type="text/yaml")
|
|
293
|
+
logger.debug("Uploaded blob '%s' (%d bytes)",
|
|
294
|
+
blob_name, len(config.flock_definition.encode()))
|
|
295
|
+
|
|
296
|
+
# 2. Persist lightweight record in the table
|
|
297
|
+
tbl_client = self.table_svc.get_table_client(self._TABLE_NAME)
|
|
298
|
+
entity = {
|
|
299
|
+
"PartitionKey": self._PARTITION_KEY,
|
|
300
|
+
"RowKey": config.share_id,
|
|
301
|
+
"agent_name": config.agent_name,
|
|
302
|
+
"created_at": config.created_at.isoformat(),
|
|
303
|
+
"share_type": config.share_type,
|
|
304
|
+
"chat_message_key": config.chat_message_key,
|
|
305
|
+
"chat_history_key": config.chat_history_key,
|
|
306
|
+
"chat_response_key": config.chat_response_key,
|
|
307
|
+
# NEW – just a few bytes, well under 64 KiB
|
|
308
|
+
"flock_blob_name": blob_name,
|
|
309
|
+
}
|
|
310
|
+
await tbl_client.upsert_entity(entity)
|
|
311
|
+
logger.info("Saved shared link %s → blob '%s'", config.share_id, blob_name)
|
|
312
|
+
return config
|
|
313
|
+
|
|
314
|
+
# -------------------------------------------------------------- get_config
|
|
292
315
|
async def get_config(self, share_id: str) -> SharedLinkConfig | None:
|
|
293
|
-
|
|
316
|
+
tbl_client = self.table_svc.get_table_client(self._TABLE_NAME)
|
|
294
317
|
try:
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
entity = await table_client.get_entity(partition_key="shared_links", row_key=share_id)
|
|
298
|
-
|
|
299
|
-
logger.debug(f"Retrieved shared link config from Azure Table Storage for ID: {share_id}")
|
|
300
|
-
return SharedLinkConfig(
|
|
301
|
-
share_id=entity["share_id"],
|
|
302
|
-
agent_name=entity["agent_name"],
|
|
303
|
-
created_at=entity["created_at"], # Pydantic will parse from ISO format
|
|
304
|
-
flock_definition=entity["flock_definition"],
|
|
305
|
-
share_type=entity.get("share_type", "agent_run"),
|
|
306
|
-
chat_message_key=entity.get("chat_message_key"),
|
|
307
|
-
chat_history_key=entity.get("chat_history_key"),
|
|
308
|
-
chat_response_key=entity.get("chat_response_key"),
|
|
309
|
-
)
|
|
318
|
+
entity = await tbl_client.get_entity(self._PARTITION_KEY, share_id)
|
|
310
319
|
except ResourceNotFoundError:
|
|
311
|
-
logger.debug(
|
|
320
|
+
logger.debug("No config entity for id '%s'", share_id)
|
|
312
321
|
return None
|
|
322
|
+
|
|
323
|
+
blob_name = entity["flock_blob_name"]
|
|
324
|
+
blob_client = self.blob_svc.get_blob_client(self._CONTAINER_NAME, blob_name)
|
|
325
|
+
try:
|
|
326
|
+
blob_bytes = await (await blob_client.download_blob()).readall()
|
|
327
|
+
flock_yaml = blob_bytes.decode()
|
|
313
328
|
except Exception as e:
|
|
314
|
-
logger.error(
|
|
315
|
-
|
|
329
|
+
logger.error("Cannot download blob '%s' for share_id=%s: %s",
|
|
330
|
+
blob_name, share_id, e, exc_info=True)
|
|
331
|
+
raise
|
|
316
332
|
|
|
333
|
+
return SharedLinkConfig(
|
|
334
|
+
share_id = share_id,
|
|
335
|
+
agent_name = entity["agent_name"],
|
|
336
|
+
created_at = entity["created_at"],
|
|
337
|
+
flock_definition = flock_yaml,
|
|
338
|
+
share_type = entity.get("share_type", "agent_run"),
|
|
339
|
+
chat_message_key = entity.get("chat_message_key"),
|
|
340
|
+
chat_history_key = entity.get("chat_history_key"),
|
|
341
|
+
chat_response_key = entity.get("chat_response_key"),
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
# ----------------------------------------------------------- delete_config
|
|
317
345
|
async def delete_config(self, share_id: str) -> bool:
|
|
318
|
-
|
|
346
|
+
tbl_client = self.table_svc.get_table_client(self._TABLE_NAME)
|
|
319
347
|
try:
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
await table_client.delete_entity(partition_key="shared_links", row_key=share_id)
|
|
323
|
-
logger.info(f"Deleted shared link config from Azure Table Storage for ID: {share_id}")
|
|
324
|
-
return True
|
|
348
|
+
entity = await tbl_client.get_entity(self._PARTITION_KEY, share_id)
|
|
325
349
|
except ResourceNotFoundError:
|
|
326
|
-
logger.info(
|
|
327
|
-
return False
|
|
328
|
-
except Exception as e:
|
|
329
|
-
logger.error(f"Error deleting config from Azure Table Storage for ID {share_id}: {e}", exc_info=True)
|
|
350
|
+
logger.info("Delete: entity %s not found", share_id)
|
|
330
351
|
return False
|
|
331
352
|
|
|
332
|
-
|
|
353
|
+
# 1. Remove blob (ignore missing blob)
|
|
354
|
+
blob_name = entity["flock_blob_name"]
|
|
355
|
+
blob_client = self.blob_svc.get_blob_client(self._CONTAINER_NAME, blob_name)
|
|
356
|
+
try:
|
|
357
|
+
await blob_client.delete_blob(delete_snapshots="include")
|
|
358
|
+
logger.debug("Deleted blob '%s'", blob_name)
|
|
359
|
+
except ResourceNotFoundError:
|
|
360
|
+
logger.warning("Blob '%s' already gone", blob_name)
|
|
361
|
+
|
|
362
|
+
# 2. Remove table row
|
|
363
|
+
await tbl_client.delete_entity(self._PARTITION_KEY, share_id)
|
|
364
|
+
logger.info("Deleted shared link %s and its blob", share_id)
|
|
365
|
+
return True
|
|
333
366
|
|
|
367
|
+
# -------------------------------------------------------- save_feedback --
|
|
334
368
|
async def save_feedback(self, record: FeedbackRecord) -> FeedbackRecord:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
"reason": record.reason,
|
|
346
|
-
"expected_response": record.expected_response,
|
|
347
|
-
"actual_response": record.actual_response,
|
|
348
|
-
"flock_name": record.flock_name,
|
|
349
|
-
"agent_name": record.agent_name,
|
|
350
|
-
"flock_definition": record.flock_definition,
|
|
351
|
-
"created_at": record.created_at.isoformat(),
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
await table_client.upsert_entity(entity)
|
|
355
|
-
logger.info(f"Saved feedback to Azure Table Storage: {record.feedback_id} (share={record.share_id})")
|
|
356
|
-
return record
|
|
357
|
-
except Exception as e:
|
|
358
|
-
logger.error(f"Error saving feedback to Azure Table Storage {record.feedback_id}: {e}", exc_info=True)
|
|
359
|
-
raise
|
|
369
|
+
tbl_client = self.table_svc.get_table_client(self._FEEDBACK_TBL_NAME)
|
|
370
|
+
entity = {
|
|
371
|
+
"PartitionKey": "feedback",
|
|
372
|
+
"RowKey": record.feedback_id,
|
|
373
|
+
**record.model_dump(exclude={"feedback_id"}) # all other fields
|
|
374
|
+
}
|
|
375
|
+
await tbl_client.upsert_entity(entity)
|
|
376
|
+
logger.info("Saved feedback %s", record.feedback_id)
|
|
377
|
+
return record
|
|
378
|
+
|
|
360
379
|
|
|
361
380
|
|
|
362
381
|
# ----------------------- Factory Function -----------------------
|
|
@@ -508,7 +508,7 @@ flock/webapp/app/api/registry_viewer.py,sha256=IoInxJiRR0yFlecG_l2_eRc6l35RQQyED
|
|
|
508
508
|
flock/webapp/app/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
509
509
|
flock/webapp/app/services/flock_service.py,sha256=olU1My3YYkrTCVIOYPgRted-8YgAop-Yi7G4gbRHTrg,14941
|
|
510
510
|
flock/webapp/app/services/sharing_models.py,sha256=XeJk1akILV_1l-cIUaG8k_eYhjV3EWBCWZ2kpwbdImA,3609
|
|
511
|
-
flock/webapp/app/services/sharing_store.py,sha256=
|
|
511
|
+
flock/webapp/app/services/sharing_store.py,sha256=Ogc2MWFS1FDu8GQ89txMP32DvWZ5NcJjQAv4mwEroYs,18121
|
|
512
512
|
flock/webapp/app/templates/theme_mapper.html,sha256=z8ZY7nmk6PiUGzD_-px7wSXcEnuBM121rMq6u-2oaCo,14249
|
|
513
513
|
flock/webapp/static/css/chat.css,sha256=Njc9gXfQzbXMrqtFJH2Yda-IQlwNPd2z4apXxzfA0sY,8169
|
|
514
514
|
flock/webapp/static/css/components.css,sha256=WnicEHy3ptPzggKmyG9_oZp3X30EMJBUW3KEXaiUCUE,6018
|
|
@@ -562,8 +562,8 @@ flock/workflow/agent_execution_activity.py,sha256=Gy6FtuVAjf0NiUXmC3syS2eJpNQF4R
|
|
|
562
562
|
flock/workflow/flock_workflow.py,sha256=iSUF_soFvWar0ffpkzE4irkDZRx0p4HnwmEBi_Ne2sY,9666
|
|
563
563
|
flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
|
|
564
564
|
flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
|
|
565
|
-
flock_core-0.4.
|
|
566
|
-
flock_core-0.4.
|
|
567
|
-
flock_core-0.4.
|
|
568
|
-
flock_core-0.4.
|
|
569
|
-
flock_core-0.4.
|
|
565
|
+
flock_core-0.4.524.dist-info/METADATA,sha256=hD_opwGCMB2Y8gDQGmnS9w_XRNKQwzCF65_EeXmjUMU,22786
|
|
566
|
+
flock_core-0.4.524.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
567
|
+
flock_core-0.4.524.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
568
|
+
flock_core-0.4.524.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
569
|
+
flock_core-0.4.524.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|