OpenRAG 0.5.0.dev22__py3-none-any.whl → 0.5.0.dev24__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.
@@ -1,8 +1,9 @@
1
1
  import logging
2
- from pathlib import Path
3
- from typing import List, Dict, Any, Optional
4
2
  from datetime import datetime
3
+ from pathlib import Path
4
+ from typing import Any
5
5
  from urllib.parse import urlparse
6
+
6
7
  import httpx
7
8
 
8
9
  from ..base import BaseConnector, ConnectorDocument, DocumentACL
@@ -23,7 +24,7 @@ class OneDriveConnector(BaseConnector):
23
24
  CONNECTOR_DESCRIPTION = "Add knowledge from OneDrive"
24
25
  CONNECTOR_ICON = "onedrive"
25
26
 
26
- def __init__(self, config: Dict[str, Any]):
27
+ def __init__(self, config: dict[str, Any]):
27
28
  super().__init__(config)
28
29
 
29
30
  logger.debug(f"OneDrive connector __init__ called with config type: {type(config)}")
@@ -63,6 +64,7 @@ class OneDriveConnector(BaseConnector):
63
64
 
64
65
  # Token file setup - use data directory for persistence
65
66
  from config.paths import get_data_file
67
+
66
68
  token_file = config.get("token_file") or get_data_file("onedrive_token.json")
67
69
  Path(token_file).parent.mkdir(parents=True, exist_ok=True)
68
70
 
@@ -91,23 +93,29 @@ class OneDriveConnector(BaseConnector):
91
93
  self.oauth = None
92
94
 
93
95
  # Track subscription ID for webhooks (note: change notifications might not be available for personal accounts)
94
- self._subscription_id: Optional[str] = None
96
+ self._subscription_id: str | None = None
95
97
 
96
98
  # Graph API defaults
97
99
  self._graph_api_version = "v1.0"
98
- self._default_params = {
99
- "$select": "id,name,size,lastModifiedDateTime,createdDateTime,webUrl,file,folder,@microsoft.graph.downloadUrl"
100
- }
101
-
100
+ self._default_params: dict[str, Any] = {}
101
+
102
102
  # Selective sync support (similar to Google Drive)
103
- self.cfg = type('OneDriveConfig', (), {
104
- 'file_ids': config.get('file_ids') or config.get('selected_files') or config.get('selected_file_ids'),
105
- 'folder_ids': config.get('folder_ids') or config.get('selected_folders') or config.get('selected_folder_ids'),
106
- })()
107
-
103
+ self.cfg = type(
104
+ "OneDriveConfig",
105
+ (),
106
+ {
107
+ "file_ids": config.get("file_ids")
108
+ or config.get("selected_files")
109
+ or config.get("selected_file_ids"),
110
+ "folder_ids": config.get("folder_ids")
111
+ or config.get("selected_folders")
112
+ or config.get("selected_folder_ids"),
113
+ },
114
+ )()
115
+
108
116
  # Cache for file metadata including download URLs
109
117
  # This allows direct download without Graph API for sharing IDs
110
- self._file_infos: Dict[str, Dict[str, Any]] = {}
118
+ self._file_infos: dict[str, dict[str, Any]] = {}
111
119
 
112
120
  @property
113
121
  def _graph_base_url(self) -> str:
@@ -115,20 +123,20 @@ class OneDriveConnector(BaseConnector):
115
123
  return f"https://graph.microsoft.com/{self._graph_api_version}"
116
124
 
117
125
  @property
118
- def base_url(self) -> Optional[str]:
126
+ def base_url(self) -> str | None:
119
127
  """Generic base URL property (OneDrive/SharePoint domain)"""
120
128
  return self._base_url
121
-
129
+
122
130
  @base_url.setter
123
131
  def base_url(self, value: str):
124
132
  """Set base URL"""
125
133
  self._base_url = value
126
134
 
127
- def set_file_infos(self, file_infos: List[Dict[str, Any]]) -> None:
135
+ def set_file_infos(self, file_infos: list[dict[str, Any]]) -> None:
128
136
  """
129
137
  Cache file metadata including download URLs for later use.
130
138
  This allows direct download without Graph API calls for sharing IDs.
131
-
139
+
132
140
  Args:
133
141
  file_infos: List of file info dicts with {id, name, mimeType, downloadUrl, size}
134
142
  """
@@ -140,7 +148,7 @@ class OneDriveConnector(BaseConnector):
140
148
  if info.get("downloadUrl"):
141
149
  logger.debug(f"Cached download URL for file {file_id}: {info.get('name')}")
142
150
 
143
- def get_cached_file_info(self, file_id: str) -> Optional[Dict[str, Any]]:
151
+ def get_cached_file_info(self, file_id: str) -> dict[str, Any] | None:
144
152
  """Get cached file info by ID."""
145
153
  return self._file_infos.get(file_id)
146
154
 
@@ -167,7 +175,7 @@ class OneDriveConnector(BaseConnector):
167
175
 
168
176
  self._authenticated = authenticated
169
177
  return authenticated
170
- except Exception as e:
178
+ except Exception:
171
179
  logger.exception("[CONNECTOR] OneDrive authentication failed")
172
180
  self._authenticated = False
173
181
  return False
@@ -178,7 +186,7 @@ class OneDriveConnector(BaseConnector):
178
186
  raise RuntimeError("OneDrive OAuth not initialized - missing credentials")
179
187
  return self.oauth.create_authorization_url(self.redirect_uri)
180
188
 
181
- async def handle_oauth_callback(self, auth_code: str) -> Dict[str, Any]:
189
+ async def handle_oauth_callback(self, auth_code: str) -> dict[str, Any]:
182
190
  """Handle OAuth callback."""
183
191
  if not self.oauth:
184
192
  raise RuntimeError("OneDrive OAuth not initialized - missing credentials")
@@ -193,39 +201,43 @@ class OneDriveConnector(BaseConnector):
193
201
  logger.error(f"OAuth callback failed: {e}")
194
202
  raise
195
203
 
196
- async def _detect_base_url(self) -> Optional[str]:
204
+ async def _detect_base_url(self) -> str | None:
197
205
  """Override base class method to detect OneDrive URL"""
198
206
  return await self._detect_onedrive_url()
199
-
200
- async def _detect_onedrive_url(self) -> Optional[str]:
207
+
208
+ async def _detect_onedrive_url(self) -> str | None:
201
209
  """Auto-detect OneDrive URL from Microsoft Graph API"""
202
210
  logger.info("_detect_onedrive_url: Starting OneDrive URL detection")
203
211
  try:
204
212
  if not self.oauth:
205
213
  logger.warning("_detect_onedrive_url: OAuth not initialized")
206
214
  return None
207
-
215
+
208
216
  access_token = self.oauth.get_access_token()
209
- logger.debug(f"_detect_onedrive_url: Got access token (length: {len(access_token) if access_token else 0})")
210
-
217
+ logger.debug(
218
+ f"_detect_onedrive_url: Got access token (length: {len(access_token) if access_token else 0})"
219
+ )
220
+
211
221
  headers = {
212
222
  "Authorization": f"Bearer {access_token}",
213
223
  "Content-Type": "application/json",
214
224
  }
215
-
225
+
216
226
  async with httpx.AsyncClient() as client:
217
227
  # Get user's default drive to extract OneDrive URL
218
228
  url = f"{self._graph_base_url}/me/drive"
219
229
  logger.info(f"_detect_onedrive_url: Calling Graph API: {url}")
220
-
230
+
221
231
  response = await client.get(url, headers=headers, timeout=30.0)
222
- logger.info(f"_detect_onedrive_url: Graph API response status: {response.status_code}")
223
-
232
+ logger.info(
233
+ f"_detect_onedrive_url: Graph API response status: {response.status_code}"
234
+ )
235
+
224
236
  if response.status_code == 200:
225
237
  data = response.json()
226
238
  web_url = data.get("webUrl", "")
227
239
  logger.info(f"_detect_onedrive_url: webUrl from response: {web_url}")
228
-
240
+
229
241
  # Extract the domain from the webUrl
230
242
  # e.g., "https://onedrive.live.com/..." or "https://company-my.sharepoint.com/..."
231
243
  if web_url:
@@ -236,9 +248,11 @@ class OneDriveConnector(BaseConnector):
236
248
  else:
237
249
  logger.warning("_detect_onedrive_url: webUrl is empty in response")
238
250
  else:
239
- logger.warning("[CONNECTOR] OneDrive detect URL failed", status_code=response.status_code)
240
-
241
- except Exception as e:
251
+ logger.warning(
252
+ f"[CONNECTOR] OneDrive detect URL failed, status_code: {response.status_code}"
253
+ )
254
+
255
+ except Exception:
242
256
  logger.exception("[CONNECTOR] OneDrive URL detection failed")
243
257
 
244
258
  return None
@@ -261,13 +275,15 @@ class OneDriveConnector(BaseConnector):
261
275
  doc = await self.get_file_content(file_id)
262
276
  self.emit(doc)
263
277
  except Exception as e:
264
- logger.error(f"Failed to sync OneDrive file {file_info.get('name', 'unknown')}: {e}")
278
+ logger.error(
279
+ f"Failed to sync OneDrive file {file_info.get('name', 'unknown')}: {e}"
280
+ )
265
281
  continue
266
282
  except Exception as e:
267
283
  logger.error(f"OneDrive sync_once failed: {e}")
268
284
  raise
269
285
 
270
- if hasattr(asyncio, 'run'):
286
+ if hasattr(asyncio, "run"):
271
287
  asyncio.run(_async_sync())
272
288
  else:
273
289
  loop = asyncio.get_event_loop()
@@ -278,7 +294,7 @@ class OneDriveConnector(BaseConnector):
278
294
  Set up real-time subscription for file changes.
279
295
  NOTE: Change notifications may not be available for personal OneDrive accounts.
280
296
  """
281
- webhook_url = self.config.get('webhook_url')
297
+ webhook_url = self.config.get("webhook_url")
282
298
  if not webhook_url:
283
299
  logger.warning("No webhook URL configured, skipping OneDrive subscription setup")
284
300
  return "no-webhook-configured"
@@ -308,7 +324,9 @@ class OneDriveConnector(BaseConnector):
308
324
  url = f"{self._graph_base_url}/subscriptions"
309
325
 
310
326
  async with httpx.AsyncClient() as client:
311
- response = await client.post(url, json=subscription_data, headers=headers, timeout=30)
327
+ response = await client.post(
328
+ url, json=subscription_data, headers=headers, timeout=30
329
+ )
312
330
  response.raise_for_status()
313
331
 
314
332
  result = response.json()
@@ -328,15 +346,13 @@ class OneDriveConnector(BaseConnector):
328
346
  def _get_subscription_expiry(self) -> str:
329
347
  """Get subscription expiry time (Graph caps duration; often <= 3 days)."""
330
348
  from datetime import datetime, timedelta
349
+
331
350
  expiry = datetime.utcnow() + timedelta(days=3)
332
351
  return expiry.strftime("%Y-%m-%dT%H:%M:%S.%fZ")
333
352
 
334
353
  async def list_files(
335
- self,
336
- page_token: Optional[str] = None,
337
- max_files: Optional[int] = None,
338
- **kwargs
339
- ) -> Dict[str, Any]:
354
+ self, page_token: str | None = None, max_files: int | None = None, **kwargs
355
+ ) -> dict[str, Any]:
340
356
  """List files from OneDrive using Microsoft Graph."""
341
357
  try:
342
358
  if not await self.authenticate():
@@ -346,7 +362,7 @@ class OneDriveConnector(BaseConnector):
346
362
  if self.cfg.file_ids or self.cfg.folder_ids:
347
363
  return await self._list_selected_files()
348
364
 
349
- files: List[Dict[str, Any]] = []
365
+ files: list[dict[str, Any]] = []
350
366
  max_files_value = max_files if max_files is not None else 100
351
367
 
352
368
  base_url = f"{self._graph_base_url}/me/drive/root/children"
@@ -363,23 +379,28 @@ class OneDriveConnector(BaseConnector):
363
379
  items = data.get("value", [])
364
380
  for item in items:
365
381
  if item.get("file"): # include files only
366
- files.append({
367
- "id": item.get("id", ""),
368
- "name": item.get("name", ""),
369
- "path": f"/drive/items/{item.get('id')}",
370
- "size": int(item.get("size", 0)),
371
- "modified": item.get("lastModifiedDateTime"),
372
- "created": item.get("createdDateTime"),
373
- "mime_type": item.get("file", {}).get("mimeType", self._get_mime_type(item.get("name", ""))),
374
- "url": item.get("webUrl", ""),
375
- "download_url": item.get("@microsoft.graph.downloadUrl"),
376
- })
382
+ files.append(
383
+ {
384
+ "id": item.get("id", ""),
385
+ "name": item.get("name", ""),
386
+ "path": f"/drive/items/{item.get('id')}",
387
+ "size": int(item.get("size", 0)),
388
+ "modified": item.get("lastModifiedDateTime"),
389
+ "created": item.get("createdDateTime"),
390
+ "mime_type": item.get("file", {}).get(
391
+ "mimeType", self._get_mime_type(item.get("name", ""))
392
+ ),
393
+ "url": item.get("webUrl", ""),
394
+ "download_url": item.get("@microsoft.graph.downloadUrl"),
395
+ }
396
+ )
377
397
 
378
398
  # Next page
379
399
  next_page_token = None
380
400
  next_link = data.get("@odata.nextLink")
381
401
  if next_link:
382
- from urllib.parse import urlparse, parse_qs
402
+ from urllib.parse import parse_qs, urlparse
403
+
383
404
  parsed = urlparse(next_link)
384
405
  query_params = parse_qs(parsed.query)
385
406
  if "$skiptoken" in query_params:
@@ -391,7 +412,7 @@ class OneDriveConnector(BaseConnector):
391
412
  logger.error(f"Failed to list OneDrive files: {e}")
392
413
  return {"files": [], "next_page_token": None}
393
414
 
394
- async def _extract_onedrive_acl(self, file_id: str, file_metadata: Dict) -> DocumentACL:
415
+ async def _extract_onedrive_acl(self, file_id: str, file_metadata: dict) -> DocumentACL:
395
416
  """
396
417
  Extract ACL from OneDrive item.
397
418
 
@@ -406,8 +427,7 @@ class OneDriveConnector(BaseConnector):
406
427
  """
407
428
  try:
408
429
  # Get access token
409
- token_data = await self.oauth.get_access_token()
410
- access_token = token_data.get("access_token")
430
+ access_token = self.oauth.get_access_token()
411
431
 
412
432
  if not access_token:
413
433
  logger.warning(f"No access token available for ACL extraction: {file_id}")
@@ -419,8 +439,7 @@ class OneDriveConnector(BaseConnector):
419
439
  # Fetch permissions
420
440
  async with httpx.AsyncClient() as client:
421
441
  response = await client.get(
422
- permissions_url,
423
- headers={"Authorization": f"Bearer {access_token}"}
442
+ permissions_url, headers={"Authorization": f"Bearer {access_token}"}
424
443
  )
425
444
 
426
445
  if response.status_code != 200:
@@ -487,13 +506,11 @@ class OneDriveConnector(BaseConnector):
487
506
  if cached_info and cached_info.get("downloadUrl"):
488
507
  logger.info(f"Using cached download URL for file {file_id}")
489
508
  content = await self._download_file_from_url(cached_info["downloadUrl"])
490
-
509
+
491
510
  acl = DocumentACL(
492
511
  owner="",
493
- user_permissions={},
494
- group_permissions={},
495
512
  )
496
-
513
+
497
514
  return ConnectorDocument(
498
515
  id=file_id,
499
516
  filename=cached_info.get("name", "Unknown"),
@@ -513,13 +530,15 @@ class OneDriveConnector(BaseConnector):
513
530
  file_metadata = await self._get_file_metadata_by_id(file_id)
514
531
  if not file_metadata:
515
532
  # Last-resort: try shares endpoint download directly if this is a sharing ID
516
- if '!' in file_id and file_id.split('!', 1)[1].startswith('s'):
517
- logger.info(f"No metadata for sharing ID {file_id}, attempting direct shares download")
533
+ if "!" in file_id and file_id.split("!", 1)[1].startswith("s"):
534
+ logger.info(
535
+ f"No metadata for sharing ID {file_id}, attempting direct shares download"
536
+ )
518
537
  token = self.oauth.get_access_token()
519
538
  headers = {"Authorization": f"Bearer {token}"}
520
539
  shares_content = await self._download_via_shares_endpoint(file_id, headers)
521
540
  if shares_content is not None:
522
- acl = DocumentACL(owner="", user_permissions={}, group_permissions={})
541
+ acl = DocumentACL(owner="")
523
542
  return ConnectorDocument(
524
543
  id=file_id,
525
544
  filename="Unknown",
@@ -564,9 +583,9 @@ class OneDriveConnector(BaseConnector):
564
583
  logger.error(f"Failed to get OneDrive file content {file_id}: {e}")
565
584
  raise
566
585
 
567
- async def _get_file_metadata_by_id(self, file_id: str) -> Optional[Dict[str, Any]]:
586
+ async def _get_file_metadata_by_id(self, file_id: str) -> dict[str, Any] | None:
568
587
  """Get file metadata by ID using Graph API.
569
-
588
+
570
589
  Handles multiple ID formats:
571
590
  - Standard item ID: uses /me/drive/items/{id}
572
591
  - Personal OneDrive format (driveId!itemId): uses /drives/{driveId}/items/{itemId}
@@ -575,7 +594,7 @@ class OneDriveConnector(BaseConnector):
575
594
  try:
576
595
  # Try different endpoints based on ID format
577
596
  item = await self._fetch_item_metadata(file_id)
578
-
597
+
579
598
  if not item:
580
599
  return None
581
600
 
@@ -595,7 +614,9 @@ class OneDriveConnector(BaseConnector):
595
614
  "size": int(item.get("size", 0)),
596
615
  "modified": item.get("lastModifiedDateTime"),
597
616
  "created": item.get("createdDateTime"),
598
- "mime_type": item.get("file", {}).get("mimeType", self._get_mime_type(item.get("name", ""))),
617
+ "mime_type": item.get("file", {}).get(
618
+ "mimeType", self._get_mime_type(item.get("name", ""))
619
+ ),
599
620
  "url": item.get("webUrl", ""),
600
621
  "download_url": item.get("@microsoft.graph.downloadUrl"),
601
622
  "isFolder": False,
@@ -607,69 +628,79 @@ class OneDriveConnector(BaseConnector):
607
628
  logger.error(f"Failed to get file metadata for {file_id}: {e}")
608
629
  return None
609
630
 
610
- async def _fetch_item_metadata(self, file_id: str) -> Optional[Dict[str, Any]]:
631
+ async def _fetch_item_metadata(self, file_id: str) -> dict[str, Any] | None:
611
632
  """Fetch item metadata, trying multiple endpoints for different ID formats."""
612
633
  import base64
634
+
613
635
  params = dict(self._default_params)
614
-
636
+
615
637
  # Check if ID contains '!' which indicates driveId!itemId format
616
- if '!' in file_id:
617
- parts = file_id.split('!', 1)
638
+ if "!" in file_id:
639
+ parts = file_id.split("!", 1)
618
640
  if len(parts) == 2:
619
641
  drive_id = parts[0]
620
642
  item_id = parts[1]
621
-
643
+
622
644
  # Handle sharing IDs (item ID starts with 's')
623
- if item_id.startswith('s'):
645
+ if item_id.startswith("s"):
624
646
  logger.info(f"Detected sharing ID format for {file_id}")
625
-
647
+
626
648
  # Try multiple encoding approaches for the shares endpoint
627
649
  share_encodings = [
628
650
  # Approach 1: Encode the full ID with "u!" prefix
629
- base64.urlsafe_b64encode(f"u!{file_id}".encode()).decode().rstrip('='),
651
+ base64.urlsafe_b64encode(f"u!{file_id}".encode()).decode().rstrip("="),
630
652
  # Approach 2: Encode just the share token with "s!" prefix
631
- base64.urlsafe_b64encode(f"s!{item_id}".encode()).decode().rstrip('='),
653
+ base64.urlsafe_b64encode(f"s!{item_id}".encode()).decode().rstrip("="),
632
654
  # Approach 3: Encode the ID directly
633
- base64.urlsafe_b64encode(file_id.encode()).decode().rstrip('='),
655
+ base64.urlsafe_b64encode(file_id.encode()).decode().rstrip("="),
634
656
  # Approach 4: Use the ID as-is (some APIs accept this)
635
657
  f"u!{file_id}",
636
658
  ]
637
-
659
+
638
660
  for i, encoded in enumerate(share_encodings):
639
661
  try:
640
662
  url = f"{self._graph_base_url}/shares/{encoded}/driveItem"
641
- logger.debug(f"Trying shares endpoint approach {i+1}: {url}")
663
+ logger.debug(f"Trying shares endpoint approach {i + 1}: {url}")
642
664
  response = await self._make_graph_request(url, params=params)
643
665
  if response.status_code == 200:
644
- logger.info(f"Shares endpoint approach {i+1} succeeded")
666
+ logger.info(f"Shares endpoint approach {i + 1} succeeded")
645
667
  return response.json()
646
668
  else:
647
- logger.debug(f"Shares approach {i+1} failed with status {response.status_code}")
669
+ logger.debug(
670
+ f"Shares approach {i + 1} failed with status {response.status_code}"
671
+ )
648
672
  except Exception as e:
649
- logger.debug(f"Shares approach {i+1} failed: {e}")
650
-
651
- # Try: /drives/{driveId}/items/{itemId} with full item ID (including 's' prefix)
652
- logger.info(f"Trying drives endpoint: /drives/{drive_id}/items/{item_id}")
673
+ logger.debug(f"Shares approach {i + 1} failed: {e}")
674
+
675
+ # Try: /drives/{driveId}/items/{file_id} with full file ID
676
+ logger.info(f"Trying drives endpoint: /drives/{drive_id}/items/{file_id}")
653
677
  try:
654
- url = f"{self._graph_base_url}/drives/{drive_id}/items/{item_id}"
678
+ url = f"{self._graph_base_url}/drives/{drive_id}/items/{file_id}"
655
679
  response = await self._make_graph_request(url, params=params)
656
680
  if response.status_code == 200:
657
681
  return response.json()
682
+ else:
683
+ logger.warning(
684
+ f"Drives endpoint failed with status {response.status_code}: {response.text}"
685
+ )
658
686
  except Exception as e:
659
- logger.debug(f"Drives endpoint failed: {e}")
660
-
661
- # Try: /drives/{driveId}/items/{itemId} without 's' prefix
662
- if item_id.startswith('s'):
687
+ logger.debug(f"Drives endpoint exception: {e}")
688
+
689
+ # Try: /drives/{driveId}/items/{clean_file_id} without 's' prefix
690
+ if item_id.startswith("s"):
663
691
  clean_item_id = item_id[1:] # Remove 's' prefix
664
- logger.info(f"Trying drives endpoint without 's' prefix: /drives/{drive_id}/items/{clean_item_id}")
692
+ clean_file_id = f"{drive_id}!{clean_item_id}"
693
+ logger.info(
694
+ f"Trying drives endpoint without 's' prefix: /drives/{drive_id}/items/{clean_file_id}"
695
+ )
665
696
  try:
666
- url = f"{self._graph_base_url}/drives/{drive_id}/items/{clean_item_id}"
697
+ url = f"{self._graph_base_url}/drives/{drive_id}/items/{clean_file_id}"
667
698
  response = await self._make_graph_request(url, params=params)
668
699
  if response.status_code == 200:
669
700
  return response.json()
670
701
  except Exception as e:
671
702
  logger.debug(f"Drives endpoint (no prefix) failed: {e}")
672
-
703
+
673
704
  # Try: /me/drive/items/{full_id} as fallback
674
705
  logger.info(f"Trying standard endpoint: /me/drive/items/{file_id}")
675
706
  try:
@@ -677,42 +708,46 @@ class OneDriveConnector(BaseConnector):
677
708
  response = await self._make_graph_request(url, params=params)
678
709
  if response.status_code == 200:
679
710
  return response.json()
711
+ else:
712
+ logger.warning(
713
+ f"Standard endpoint failed with status {response.status_code}: {response.text}"
714
+ )
680
715
  except Exception as e:
681
- logger.debug(f"Standard endpoint failed: {e}")
716
+ logger.debug(f"Standard endpoint exception: {e}")
682
717
  else:
683
718
  # Standard item ID without '!'
684
719
  url = f"{self._graph_base_url}/me/drive/items/{file_id}"
685
720
  response = await self._make_graph_request(url, params=params)
686
721
  if response.status_code == 200:
687
722
  return response.json()
688
-
723
+
689
724
  logger.error(f"All endpoints failed for file_id: {file_id}")
690
725
  return None
691
726
 
692
727
  async def _download_file_content(self, file_id: str) -> bytes:
693
728
  """Download file content by file ID using Graph API.
694
-
729
+
695
730
  Handles multiple ID formats like _get_file_metadata_by_id.
696
731
  """
697
732
  try:
698
733
  token = self.oauth.get_access_token()
699
734
  headers = {"Authorization": f"Bearer {token}"}
700
-
735
+
701
736
  # Build URL based on ID format
702
- if '!' in file_id:
703
- parts = file_id.split('!', 1)
737
+ if "!" in file_id:
738
+ parts = file_id.split("!", 1)
704
739
  if len(parts) == 2:
705
740
  drive_id = parts[0]
706
741
  item_id = parts[1]
707
-
742
+
708
743
  # If this looks like a sharing ID (starts with 's'), try shares endpoint first
709
- if item_id.startswith('s'):
744
+ if item_id.startswith("s"):
710
745
  content = await self._download_via_shares_endpoint(file_id, headers)
711
746
  if content is not None:
712
747
  return content
713
748
 
714
- # Try drives endpoint for driveId!itemId format (including the 's' prefix)
715
- url = f"{self._graph_base_url}/drives/{drive_id}/items/{item_id}/content"
749
+ # Try drives endpoint for driveId!itemId format
750
+ url = f"{self._graph_base_url}/drives/{drive_id}/items/{file_id}/content"
716
751
  logger.info(f"Downloading via drives endpoint: {url}")
717
752
  else:
718
753
  url = f"{self._graph_base_url}/me/drive/items/{file_id}/content"
@@ -728,31 +763,37 @@ class OneDriveConnector(BaseConnector):
728
763
  logger.error(f"Failed to download file content for {file_id}: {e}")
729
764
  raise
730
765
 
731
- async def _download_via_shares_endpoint(self, file_id: str, headers: Dict[str, str]) -> Optional[bytes]:
766
+ async def _download_via_shares_endpoint(
767
+ self, file_id: str, headers: dict[str, str]
768
+ ) -> bytes | None:
732
769
  """
733
770
  Attempt to download content using the Graph /shares endpoint for sharing IDs.
734
771
  """
735
772
  import base64
736
773
 
737
774
  share_encodings = [
738
- base64.urlsafe_b64encode(f"u!{file_id}".encode()).decode().rstrip('='),
739
- base64.urlsafe_b64encode(f"s!{file_id}".encode()).decode().rstrip('='),
740
- base64.urlsafe_b64encode(file_id.encode()).decode().rstrip('='),
775
+ base64.urlsafe_b64encode(f"u!{file_id}".encode()).decode().rstrip("="),
776
+ base64.urlsafe_b64encode(f"s!{file_id}".encode()).decode().rstrip("="),
777
+ base64.urlsafe_b64encode(file_id.encode()).decode().rstrip("="),
741
778
  f"u!{file_id}",
742
779
  ]
743
780
 
744
781
  for i, encoded in enumerate(share_encodings):
745
782
  try:
746
783
  url = f"{self._graph_base_url}/shares/{encoded}/driveItem/content"
747
- logger.info(f"Attempting shares download (approach {i+1}): {url}")
784
+ logger.info(f"Attempting shares download (approach {i + 1}): {url}")
748
785
  async with httpx.AsyncClient() as client:
749
- response = await client.get(url, headers=headers, timeout=60, follow_redirects=True)
786
+ response = await client.get(
787
+ url, headers=headers, timeout=60, follow_redirects=True
788
+ )
750
789
  if response.status_code == 200:
751
790
  return response.content
752
791
  else:
753
- logger.debug(f"Shares download approach {i+1} failed with status {response.status_code}")
792
+ logger.debug(
793
+ f"Shares download approach {i + 1} failed with status {response.status_code}"
794
+ )
754
795
  except Exception as e:
755
- logger.debug(f"Shares download approach {i+1} failed: {e}")
796
+ logger.debug(f"Shares download approach {i + 1} failed: {e}")
756
797
 
757
798
  return None
758
799
 
@@ -767,20 +808,25 @@ class OneDriveConnector(BaseConnector):
767
808
  logger.error(f"Failed to download from URL {download_url}: {e}")
768
809
  raise
769
810
 
770
- def _parse_graph_date(self, date_str: Optional[str]) -> datetime:
811
+ def _parse_graph_date(self, date_str: str | None) -> datetime:
771
812
  """Parse Microsoft Graph date string to datetime."""
772
813
  if not date_str:
773
814
  return datetime.now()
774
815
  try:
775
- if date_str.endswith('Z'):
816
+ if date_str.endswith("Z"):
776
817
  return datetime.fromisoformat(date_str[:-1]).replace(tzinfo=None)
777
818
  else:
778
- return datetime.fromisoformat(date_str.replace('T', ' '))
819
+ return datetime.fromisoformat(date_str.replace("T", " "))
779
820
  except (ValueError, AttributeError):
780
821
  return datetime.now()
781
822
 
782
- async def _make_graph_request(self, url: str, method: str = "GET",
783
- data: Optional[Dict] = None, params: Optional[Dict] = None) -> httpx.Response:
823
+ async def _make_graph_request(
824
+ self,
825
+ url: str,
826
+ method: str = "GET",
827
+ data: dict | None = None,
828
+ params: dict | None = None,
829
+ ) -> httpx.Response:
784
830
  """Make authenticated API request to Microsoft Graph."""
785
831
  token = self.oauth.get_access_token()
786
832
  headers = {
@@ -801,25 +847,25 @@ class OneDriveConnector(BaseConnector):
801
847
  response.raise_for_status()
802
848
  return response
803
849
 
804
- async def _list_selected_files(self) -> Dict[str, Any]:
850
+ async def _list_selected_files(self) -> dict[str, Any]:
805
851
  """List only selected files/folders (selective sync)."""
806
- files: List[Dict[str, Any]] = []
807
-
852
+ files: list[dict[str, Any]] = []
853
+
808
854
  # Process selected file IDs
809
855
  if self.cfg.file_ids:
810
856
  for file_id in self.cfg.file_ids:
811
857
  try:
812
858
  file_meta = await self._get_file_metadata_by_id(file_id)
813
- if file_meta and not file_meta.get('isFolder', False):
859
+ if file_meta and not file_meta.get("isFolder", False):
814
860
  files.append(file_meta)
815
- elif file_meta and file_meta.get('isFolder', False):
861
+ elif file_meta and file_meta.get("isFolder", False):
816
862
  # If it's a folder, expand its contents
817
863
  folder_files = await self._list_folder_contents(file_id)
818
864
  files.extend(folder_files)
819
865
  except Exception as e:
820
866
  logger.warning(f"Failed to get file {file_id}: {e}")
821
867
  continue
822
-
868
+
823
869
  # Process selected folder IDs
824
870
  if self.cfg.folder_ids:
825
871
  for folder_id in self.cfg.folder_ids:
@@ -829,20 +875,20 @@ class OneDriveConnector(BaseConnector):
829
875
  except Exception as e:
830
876
  logger.warning(f"Failed to list folder {folder_id}: {e}")
831
877
  continue
832
-
878
+
833
879
  return {"files": files, "next_page_token": None}
834
-
835
- async def _list_folder_contents(self, folder_id: str) -> List[Dict[str, Any]]:
880
+
881
+ async def _list_folder_contents(self, folder_id: str) -> list[dict[str, Any]]:
836
882
  """List all files in a folder recursively."""
837
- files: List[Dict[str, Any]] = []
838
-
883
+ files: list[dict[str, Any]] = []
884
+
839
885
  try:
840
886
  url = f"{self._graph_base_url}/me/drive/items/{folder_id}/children"
841
887
  params = dict(self._default_params)
842
-
888
+
843
889
  response = await self._make_graph_request(url, params=params)
844
890
  data = response.json()
845
-
891
+
846
892
  items = data.get("value", [])
847
893
  for item in items:
848
894
  if item.get("file"): # It's a file
@@ -854,35 +900,37 @@ class OneDriveConnector(BaseConnector):
854
900
  files.extend(subfolder_files)
855
901
  except Exception as e:
856
902
  logger.error(f"Failed to list folder contents for {folder_id}: {e}")
857
-
903
+
858
904
  return files
859
905
 
860
906
  def _get_mime_type(self, filename: str) -> str:
861
907
  """Get MIME type based on file extension."""
862
908
  import mimetypes
909
+
863
910
  mime_type, _ = mimetypes.guess_type(filename)
864
911
  return mime_type or "application/octet-stream"
865
912
 
866
913
  # Webhook methods - BaseConnector interface
867
- def handle_webhook_validation(self, request_method: str,
868
- headers: Dict[str, str],
869
- query_params: Dict[str, str]) -> Optional[str]:
914
+ def handle_webhook_validation(
915
+ self, request_method: str, headers: dict[str, str], query_params: dict[str, str]
916
+ ) -> str | None:
870
917
  """Handle webhook validation (Graph API specific)."""
871
918
  if request_method == "POST" and "validationToken" in query_params:
872
919
  return query_params["validationToken"]
873
920
  return None
874
921
 
875
- def extract_webhook_channel_id(self, payload: Dict[str, Any],
876
- headers: Dict[str, str]) -> Optional[str]:
922
+ def extract_webhook_channel_id(
923
+ self, payload: dict[str, Any], headers: dict[str, str]
924
+ ) -> str | None:
877
925
  """Extract channel/subscription ID from webhook payload."""
878
926
  notifications = payload.get("value", [])
879
927
  if notifications:
880
928
  return notifications[0].get("subscriptionId")
881
929
  return None
882
930
 
883
- async def handle_webhook(self, payload: Dict[str, Any]) -> List[str]:
931
+ async def handle_webhook(self, payload: dict[str, Any]) -> list[str]:
884
932
  """Handle webhook notification and return affected file IDs."""
885
- affected_files: List[str] = []
933
+ affected_files: list[str] = []
886
934
  notifications = payload.get("value", [])
887
935
  for notification in notifications:
888
936
  resource = notification.get("resource")
@@ -914,7 +962,9 @@ class OneDriveConnector(BaseConnector):
914
962
  logger.info(f"OneDrive subscription {subscription_id} cleaned up successfully")
915
963
  return True
916
964
  else:
917
- logger.warning(f"Unexpected response cleaning up subscription: {response.status_code}")
965
+ logger.warning(
966
+ f"Unexpected response cleaning up subscription: {response.status_code}"
967
+ )
918
968
  return False
919
969
 
920
970
  except Exception as e:
@@ -1,8 +1,7 @@
1
- import os
2
1
  import json
3
2
  import logging
4
- from typing import Optional, Dict, Any
5
-
3
+ import os
4
+ from typing import Any
6
5
 
7
6
  import msal
8
7
 
@@ -25,16 +24,9 @@ class OneDriveOAuth:
25
24
  "Files.Read",
26
25
  "Files.Read.All", # Access all files user can access
27
26
  "Files.Read.Selected",
28
- "Sites.Read.All", # Read SharePoint sites (for File Picker and OneDrive for Business)
29
- "offline_access"
30
- ]
31
- RESOURCE_SCOPES = [
32
- "User.Read",
33
- "Files.Read",
34
- "Files.Read.All",
35
- "Files.Read.Selected",
36
- "Sites.Read.All"
27
+ "offline_access",
37
28
  ]
29
+ RESOURCE_SCOPES = ["User.Read", "Files.Read", "Files.Read.All", "Files.Read.Selected"]
38
30
  SCOPES = AUTH_SCOPES # Backward-compat alias if something references .SCOPES
39
31
 
40
32
  # Kept for reference; MSAL derives endpoints from `authority`
@@ -67,7 +59,7 @@ class OneDriveOAuth:
67
59
  self.authority = authority
68
60
  self.allow_json_refresh = allow_json_refresh
69
61
  self.token_cache = msal.SerializableTokenCache()
70
- self._current_account = None
62
+ self._current_account: dict[str, Any] | None = None
71
63
 
72
64
  # Initialize MSAL Confidential Client
73
65
  self.app = msal.ConfidentialClientApplication(
@@ -81,10 +73,10 @@ class OneDriveOAuth:
81
73
  """Load existing credentials from token file (async)."""
82
74
  try:
83
75
  from utils.encryption import read_encrypted_file
84
-
76
+
85
77
  logger.debug(f"OneDrive OAuth loading credentials from: {self.token_file}")
86
78
  cache_data, needs_upgrade = await read_encrypted_file(self.token_file)
87
-
79
+
88
80
  if cache_data and cache_data.strip():
89
81
  # 1) Try legacy flat JSON first
90
82
  try:
@@ -112,15 +104,20 @@ class OneDriveOAuth:
112
104
  accounts = self.app.get_accounts()
113
105
  logger.debug(f"Found {len(accounts)} accounts in MSAL cache")
114
106
  if accounts:
115
- self._current_account = accounts[0]
116
- logger.debug(f"Set current account: {self._current_account.get('username', 'no username')}")
117
-
107
+ account = accounts[0]
108
+ self._current_account = account
109
+ logger.debug(f"Set current account: {account.get('username', 'no username')}")
110
+
118
111
  if needs_upgrade:
119
112
  await self.save_cache()
120
113
 
121
114
  # Use RESOURCE_SCOPES (no reserved scopes) for silent acquisition
122
- result = self.app.acquire_token_silent(self.RESOURCE_SCOPES, account=self._current_account)
123
- logger.debug(f"Silent token acquisition result keys: {list(result.keys()) if result else 'None'}")
115
+ result = self.app.acquire_token_silent(
116
+ self.RESOURCE_SCOPES, account=self._current_account
117
+ )
118
+ logger.debug(
119
+ f"Silent token acquisition result keys: {list(result.keys()) if result else 'None'}"
120
+ )
124
121
  if result and "access_token" in result:
125
122
  logger.debug("Silent token acquisition successful")
126
123
  if getattr(self.token_cache, "has_state_changed", False):
@@ -134,7 +131,7 @@ class OneDriveOAuth:
134
131
 
135
132
  return False
136
133
 
137
- except Exception as e:
134
+ except Exception:
138
135
  logger.exception("[CONNECTOR] OneDrive credential load failed")
139
136
  return False
140
137
 
@@ -166,15 +163,24 @@ class OneDriveOAuth:
166
163
  accounts = self.app.get_accounts()
167
164
  logger.debug(f"After refresh, found {len(accounts)} accounts")
168
165
  if accounts:
169
- self._current_account = accounts[0]
170
- logger.debug(f"Set current account after refresh: {self._current_account.get('username', 'no username')}")
166
+ account = accounts[0]
167
+ self._current_account = account
168
+ logger.debug(
169
+ f"Set current account after refresh: {account.get('username', 'no username')}"
170
+ )
171
171
  return True
172
172
 
173
173
  # Error handling
174
- err = (result or {}).get("error_description") or (result or {}).get("error") or "Unknown error"
174
+ err = (
175
+ (result or {}).get("error_description")
176
+ or (result or {}).get("error")
177
+ or "Unknown error"
178
+ )
175
179
  logger.error(f"Refresh token failed: {err}")
176
180
 
177
- if any(code in err for code in ("AADSTS70000", "invalid_grant", "interaction_required")):
181
+ if any(
182
+ code in err for code in ("AADSTS70000", "invalid_grant", "interaction_required")
183
+ ):
178
184
  logger.warning(
179
185
  "Refresh denied due to unauthorized/expired scopes or invalid grant. "
180
186
  "Delete the token file and perform interactive sign-in with correct scopes."
@@ -182,7 +188,7 @@ class OneDriveOAuth:
182
188
 
183
189
  return False
184
190
 
185
- except Exception as e:
191
+ except Exception:
186
192
  logger.exception("[CONNECTOR] OneDrive JSON token refresh failed")
187
193
  return False
188
194
 
@@ -197,18 +203,19 @@ class OneDriveOAuth:
197
203
  cache_data = self.token_cache.serialize()
198
204
  if cache_data:
199
205
  from utils.encryption import write_encrypted_file
206
+
200
207
  await write_encrypted_file(self.token_file, cache_data)
201
-
208
+
202
209
  logger.debug(f"Token cache saved to {self.token_file}")
203
210
  except Exception as e:
204
211
  logger.error(f"Failed to save token cache: {e}")
205
212
 
206
- def create_authorization_url(self, redirect_uri: str, state: Optional[str] = None) -> str:
213
+ def create_authorization_url(self, redirect_uri: str, state: str | None = None) -> str:
207
214
  """Create authorization URL for OAuth flow."""
208
215
  # Store redirect URI for later use in callback
209
216
  self._redirect_uri = redirect_uri
210
217
 
211
- kwargs: Dict[str, Any] = {
218
+ kwargs: dict[str, Any] = {
212
219
  # Interactive auth includes offline_access
213
220
  "scopes": self.AUTH_SCOPES,
214
221
  "redirect_uri": redirect_uri,
@@ -231,7 +238,7 @@ class OneDriveOAuth:
231
238
  try:
232
239
  result = self.app.acquire_token_by_authorization_code(
233
240
  authorization_code,
234
- scopes=self.AUTH_SCOPES, # same as authorize step
241
+ scopes=self.AUTH_SCOPES, # same as authorize step
235
242
  redirect_uri=redirect_uri,
236
243
  )
237
244
 
@@ -244,7 +251,11 @@ class OneDriveOAuth:
244
251
  logger.info("OneDrive OAuth authorization successful")
245
252
  return True
246
253
 
247
- error_msg = (result or {}).get("error_description") or (result or {}).get("error") or "Unknown error"
254
+ error_msg = (
255
+ (result or {}).get("error_description")
256
+ or (result or {}).get("error")
257
+ or "Unknown error"
258
+ )
248
259
  logger.error(f"OneDrive OAuth authorization failed: {error_msg}")
249
260
  return False
250
261
 
@@ -262,29 +273,47 @@ class OneDriveOAuth:
262
273
  load_result = await self.load_credentials()
263
274
  logger.info(f"OneDrive is_authenticated: load_credentials returned {load_result}")
264
275
 
265
- logger.info(f"OneDrive is_authenticated: current_account={self._current_account is not None}")
266
-
276
+ logger.info(
277
+ f"OneDrive is_authenticated: current_account={self._current_account is not None}"
278
+ )
279
+
267
280
  # Try to get a token (MSAL will refresh if needed)
268
281
  if self._current_account:
269
- logger.info(f"OneDrive is_authenticated: Trying acquire_token_silent with account {self._current_account.get('username', 'unknown')}")
282
+ logger.info(
283
+ f"OneDrive is_authenticated: Trying acquire_token_silent with account {self._current_account.get('username', 'unknown')}"
284
+ )
270
285
  logger.info(f"OneDrive is_authenticated: RESOURCE_SCOPES={self.RESOURCE_SCOPES}")
271
- result = self.app.acquire_token_silent(self.RESOURCE_SCOPES, account=self._current_account)
286
+ result = self.app.acquire_token_silent(
287
+ self.RESOURCE_SCOPES, account=self._current_account
288
+ )
272
289
  if result and "access_token" in result:
273
- logger.info("OneDrive is_authenticated: Successfully acquired token with account")
290
+ logger.info(
291
+ "OneDrive is_authenticated: Successfully acquired token with account"
292
+ )
274
293
  if getattr(self.token_cache, "has_state_changed", False):
275
294
  await self.save_cache()
276
295
  return True
277
296
  else:
278
- error_msg = (result or {}).get("error") or (result or {}).get("error_description") or "No result returned"
279
- logger.warning(f"OneDrive is_authenticated: Token acquisition failed for current account: {error_msg}")
297
+ error_msg = (
298
+ (result or {}).get("error")
299
+ or (result or {}).get("error_description")
300
+ or "No result returned"
301
+ )
302
+ logger.warning(
303
+ f"OneDrive is_authenticated: Token acquisition failed for current account: {error_msg}"
304
+ )
280
305
  logger.warning(f"OneDrive is_authenticated: Full result: {result}")
281
306
 
282
307
  # Fallback: try without specific account
283
- logger.info("OneDrive is_authenticated: Fallback - trying acquire_token_silent without account")
308
+ logger.info(
309
+ "OneDrive is_authenticated: Fallback - trying acquire_token_silent without account"
310
+ )
284
311
  result = self.app.acquire_token_silent(self.RESOURCE_SCOPES, account=None)
285
312
  if result and "access_token" in result:
286
313
  accounts = self.app.get_accounts()
287
- logger.info(f"OneDrive is_authenticated: Fallback succeeded, found {len(accounts)} accounts")
314
+ logger.info(
315
+ f"OneDrive is_authenticated: Fallback succeeded, found {len(accounts)} accounts"
316
+ )
288
317
  if accounts:
289
318
  self._current_account = accounts[0]
290
319
  if getattr(self.token_cache, "has_state_changed", False):
@@ -294,23 +323,31 @@ class OneDriveOAuth:
294
323
  logger.warning(f"OneDrive is_authenticated: Fallback also failed, result: {result}")
295
324
  return False
296
325
 
297
- except Exception as e:
326
+ except Exception:
298
327
  logger.exception("[CONNECTOR] OneDrive is_authenticated failed")
299
328
  return False
300
329
 
301
330
  def get_access_token(self) -> str:
302
331
  """Get an access token for Microsoft Graph."""
303
- logger.info(f"OneDrive get_access_token: Starting, current_account={self._current_account is not None}")
332
+ logger.info(
333
+ f"OneDrive get_access_token: Starting, current_account={self._current_account is not None}"
334
+ )
304
335
  try:
305
336
  # Try with current account first
306
337
  if self._current_account:
307
- logger.info(f"OneDrive get_access_token: Trying with account {self._current_account.get('username', 'unknown')}")
308
- result = self.app.acquire_token_silent(self.RESOURCE_SCOPES, account=self._current_account)
338
+ logger.info(
339
+ f"OneDrive get_access_token: Trying with account {self._current_account.get('username', 'unknown')}"
340
+ )
341
+ result = self.app.acquire_token_silent(
342
+ self.RESOURCE_SCOPES, account=self._current_account
343
+ )
309
344
  if result and "access_token" in result:
310
345
  logger.info("OneDrive get_access_token: Success with current account")
311
346
  return result["access_token"]
312
347
  else:
313
- logger.warning(f"OneDrive get_access_token: Failed with account, result: {result}")
348
+ logger.warning(
349
+ f"OneDrive get_access_token: Failed with account, result: {result}"
350
+ )
314
351
 
315
352
  # Fallback: try without specific account
316
353
  logger.info("OneDrive get_access_token: Fallback - trying without account")
@@ -320,11 +357,15 @@ class OneDriveOAuth:
320
357
  return result["access_token"]
321
358
 
322
359
  # If we get here, authentication has failed
323
- error_msg = (result or {}).get("error_description") or (result or {}).get("error") or "No valid authentication"
360
+ error_msg = (
361
+ (result or {}).get("error_description")
362
+ or (result or {}).get("error")
363
+ or "No valid authentication"
364
+ )
324
365
  logger.error(f"OneDrive get_access_token: All attempts failed, error: {error_msg}")
325
366
  raise ValueError(f"Failed to acquire access token: {error_msg}")
326
367
 
327
- except Exception as e:
368
+ except Exception:
328
369
  logger.exception("[CONNECTOR] OneDrive get_access_token failed")
329
370
  raise
330
371
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openrag
3
- Version: 0.5.0.dev22
3
+ Version: 0.5.0.dev24
4
4
  Summary: OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
5
5
  Classifier: Development Status :: 4 - Beta
6
6
  Classifier: Environment :: Console
@@ -61,8 +61,8 @@ connectors/ibm_cos/connector.py,sha256=HqgfpaDKl-q5gHzIiLCtCXrnaMnMX2E1HM7Xv6Yq6
61
61
  connectors/ibm_cos/models.py,sha256=tQc0xSH_bFP_T-lqj010nJLqe6NWF2wFPCvuVIVzUq4,630
62
62
  connectors/ibm_cos/support.py,sha256=0vWHSfYQiZRaPk0T0aIzTG7NYwbEdh7WWCyJAj2PhMU,2205
63
63
  connectors/onedrive/__init__.py,sha256=YJs21dmKpdWRobGEyQex-j8Hg6y7zwpkZvOOqPGQD08,124
64
- connectors/onedrive/connector.py,sha256=Z2tD43hjqw6G-oQxm9vyz7gkhQ5Rg2t75Jq1is8QSCM,40877
65
- connectors/onedrive/oauth.py,sha256=q6o7zj8ke5uEUnjNJFkP_hTQEYCNVBKThmgmlwvqpB8,16548
64
+ connectors/onedrive/connector.py,sha256=O02zSrHhLUsB6Bj3nYiQcHz5hatj5YVzH_6N6M4q1d0,41263
65
+ connectors/onedrive/oauth.py,sha256=OPMeC-uaTLUMGpEWNZzgjGxkRtfxbd4ejZ4LarieFs0,17215
66
66
  connectors/sharepoint/__init__.py,sha256=uZJE-UKNUdaugXLelLbsqpxuwWalW4306yMhwYbYiLY,132
67
67
  connectors/sharepoint/connector.py,sha256=6aNE_1cffidmGkYoXFhJx8STegqMAqlw7__OdRLdA5s,37906
68
68
  connectors/sharepoint/oauth.py,sha256=H7rE6DDlXfTPZTn64E_7crJQtKzuc_lC2UHo0m2FIS4,20272
@@ -73,7 +73,7 @@ models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  models/processors.py,sha256=e6qpstQq9DyHM4UMEUfjQqBoVO4xeLmSLkQcyt4oca0,35539
74
74
  models/tasks.py,sha256=9iINXQZxA9-hcYzG8xC_baBfLa2w6gcRPJdQHsx_Kms,1643
75
75
  models/url.py,sha256=92rsrLLyIqUErYipYz5QwUNTdHwJ2jBRV7PIVpncTyo,5764
76
- openrag-0.5.0.dev22.dist-info/licenses/LICENSE,sha256=jWcnPXkUxEinX60Yn-_zjsY9i84vz2QSb0fi53djOkg,11334
76
+ openrag-0.5.0.dev24.dist-info/licenses/LICENSE,sha256=jWcnPXkUxEinX60Yn-_zjsY9i84vz2QSb0fi53djOkg,11334
77
77
  services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
78
  services/api_key_service.py,sha256=NMz2ohJo0jcuHjDN3tHuzhCTVo6lsOqAkUhozzmWSv0,11720
79
79
  services/auth_service.py,sha256=nNxKuCHh0ziHuHU18EGEUnf242h1XYsfbrbfWTmCmQE,22125
@@ -159,8 +159,8 @@ utils/telemetry/__init__.py,sha256=xoStY8hoYWnVe0B_jNthSdzRb7AxCT0rhM8ba9Q0Obg,2
159
159
  utils/telemetry/category.py,sha256=wei3V5WyUaiadYjEE5s0ys9PY0TjnebIvTykQU0P_2k,1114
160
160
  utils/telemetry/client.py,sha256=RhjW1a27w7W6gHt9X7AxdRPdZGmCEQDPskkxj5nsuiQ,12500
161
161
  utils/telemetry/message_id.py,sha256=IAu0wBVNOGPcSlQ0bAzvqIYr1Ac_n8wSTSxXzq_tiV0,9634
162
- openrag-0.5.0.dev22.dist-info/METADATA,sha256=u-a-0RRdjOY6_U6LxnhJ89LymdgfUrqiKnT_Z1Pr37M,7819
163
- openrag-0.5.0.dev22.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
164
- openrag-0.5.0.dev22.dist-info/entry_points.txt,sha256=ArKNHB63I3K8vynNkogvZOLmmQFpIsHDL7MvreCmju4,45
165
- openrag-0.5.0.dev22.dist-info/top_level.txt,sha256=5vfLBIkzuwBJrizhCSZiXV7NTzTRIMlNLsyzYDEeCF8,125
166
- openrag-0.5.0.dev22.dist-info/RECORD,,
162
+ openrag-0.5.0.dev24.dist-info/METADATA,sha256=_I6uacsYzfvS8bzCw1kVyq1bxGtuCAwnr5GPUX9SK3E,7819
163
+ openrag-0.5.0.dev24.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
164
+ openrag-0.5.0.dev24.dist-info/entry_points.txt,sha256=ArKNHB63I3K8vynNkogvZOLmmQFpIsHDL7MvreCmju4,45
165
+ openrag-0.5.0.dev24.dist-info/top_level.txt,sha256=5vfLBIkzuwBJrizhCSZiXV7NTzTRIMlNLsyzYDEeCF8,125
166
+ openrag-0.5.0.dev24.dist-info/RECORD,,