symbolicai 0.20.0__py3-none-any.whl → 0.20.1__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.
symai/__init__.py CHANGED
@@ -33,7 +33,7 @@ os.environ['TOKENIZERS_PARALLELISM'] = "false"
33
33
  # Create singleton instance
34
34
  config_manager = settings.SymAIConfig()
35
35
 
36
- SYMAI_VERSION = "0.20.0"
36
+ SYMAI_VERSION = "0.20.1"
37
37
  __version__ = SYMAI_VERSION
38
38
  __root_dir__ = config_manager.config_dir
39
39
 
@@ -230,6 +230,8 @@ class SearchResult(Result):
230
230
 
231
231
 
232
232
  class GPTXSearchEngine(Engine):
233
+ MAX_ALLOWED_DOMAINS = 20
234
+
233
235
  def __init__(self, api_key: str | None = None, model: str | None = None):
234
236
  super().__init__()
235
237
  self.config = deepcopy(SYMAI_CONFIG)
@@ -250,6 +252,65 @@ class GPTXSearchEngine(Engine):
250
252
  return 'search'
251
253
  return super().id() # default to unregistered
252
254
 
255
+ def _extract_netloc(self, raw_domain: str | None) -> str | None:
256
+ if not isinstance(raw_domain, str):
257
+ return None
258
+ candidate = raw_domain.strip()
259
+ if not candidate:
260
+ return None
261
+ parsed = urlsplit(candidate if '://' in candidate else f"//{candidate}")
262
+ netloc = parsed.netloc or parsed.path
263
+ if not netloc:
264
+ return None
265
+ if '@' in netloc:
266
+ netloc = netloc.split('@', 1)[1]
267
+ if ':' in netloc:
268
+ netloc = netloc.split(':', 1)[0]
269
+ netloc = netloc.strip('.').strip()
270
+ if not netloc:
271
+ return None
272
+ return netloc.lower()
273
+
274
+ def _normalize_allowed_domains(self, domains: list[str] | None) -> list[str]:
275
+ if not domains or not isinstance(domains, list):
276
+ return []
277
+
278
+ normalized: list[str] = []
279
+ seen: set[str] = set()
280
+ for domain in domains:
281
+ netloc = self._extract_netloc(domain)
282
+ if not netloc or netloc in seen:
283
+ continue
284
+ # Validate that netloc is actually a valid domain
285
+ if not self._is_domain(netloc):
286
+ continue
287
+ normalized.append(netloc)
288
+ seen.add(netloc)
289
+ if len(normalized) >= self.MAX_ALLOWED_DOMAINS:
290
+ break
291
+ return normalized
292
+
293
+ def _is_domain(self, s: str) -> bool:
294
+ _label_re = re.compile(r"^[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?$")
295
+ if not s:
296
+ return False
297
+ host = s.strip().rstrip(".")
298
+ # If the input might be a URL, extract the hostname via urllib:
299
+ if "://" in host or "/" in host or "@" in host:
300
+ host = urlsplit(host if "://" in host else f"//{host}").hostname or ""
301
+ if not host:
302
+ return False
303
+ try:
304
+ host_ascii = host.encode("idna").decode("ascii")
305
+ except Exception:
306
+ return False
307
+ if len(host_ascii) > 253:
308
+ return False
309
+ labels = host_ascii.split(".")
310
+ if len(labels) < 2: # require a dot (reject "google")
311
+ return False
312
+ return all(_label_re.fullmatch(lbl or "") for lbl in labels)
313
+
253
314
  def command(self, *args, **kwargs):
254
315
  super().command(*args, **kwargs)
255
316
  if 'SEARCH_ENGINE_API_KEY' in kwargs:
@@ -266,6 +327,12 @@ class GPTXSearchEngine(Engine):
266
327
  if user_location:
267
328
  tool_definition['user_location'] = user_location
268
329
 
330
+ allowed_domains = self._normalize_allowed_domains(kwargs.get('allowed_domains'))
331
+ if allowed_domains:
332
+ tool_definition['filters'] = {
333
+ 'allowed_domains': allowed_domains
334
+ }
335
+
269
336
  self.model = kwargs.get('model', self.model) # Important for MetadataTracker to work correctly
270
337
  payload = {
271
338
  "model": self.model,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: symbolicai
3
- Version: 0.20.0
3
+ Version: 0.20.1
4
4
  Summary: A Neurosymbolic Perspective on Large Language Models
5
5
  Author-email: Marius-Constantin Dinu <marius@extensity.ai>, Leoveanu-Condrei Claudiu <leo@extensity.ai>
6
6
  License: BSD 3-Clause License
@@ -1,5 +1,5 @@
1
1
  symai/TERMS_OF_SERVICE.md,sha256=HN42UXVI_wAVDHjMShzy_k7xAsbjXaATNeMKcIte_eg,91409
2
- symai/__init__.py,sha256=KtGPEQThW5g7PZrdXCc2hg-3I-TOboDLu2gaxQWwSpc,16464
2
+ symai/__init__.py,sha256=fsXUaTEBN_pJJ24Fh59ZPC39HPMGEH_w7Qr7Llwpyhk,16464
3
3
  symai/chat.py,sha256=vqEe7NqSWdzr9ixkko_094SR1LIbgPLcZxQ8W7782N4,12775
4
4
  symai/components.py,sha256=vgIq-cC8rqZG9PAPUB52Y5RGFEKrxFUCWzqzrPzLNvw,52232
5
5
  symai/constraints.py,sha256=S1ywLB8nFQy4-beDoJz6IvLTiZHGR8Fu5RNTY4v5zG0,1641
@@ -56,7 +56,7 @@ symai/backend/engines/neurosymbolic/engine_openai_gptX_completion.py,sha256=YgxR
56
56
  symai/backend/engines/neurosymbolic/engine_openai_gptX_reasoning.py,sha256=QVbyZybUPSAQHiA66V6we2W2dAsk52g1kJ7kMdGqb9I,22951
57
57
  symai/backend/engines/ocr/engine_apilayer.py,sha256=hZo4lk0ECRIzaGEpmCSNjR5Xrh8mwkKMD2ddpdgioVU,2399
58
58
  symai/backend/engines/output/engine_stdout.py,sha256=2hhyhMHFJTfjVRaODYd_5XPnV9pT03URcpYbeMY_USU,951
59
- symai/backend/engines/search/engine_openai.py,sha256=8pzzQ4yU3g4Rp6VesyOUFyJgTBrWzXYWNUyo5jlgbNw,11503
59
+ symai/backend/engines/search/engine_openai.py,sha256=s0ZlcIRDGrzm24M9uhPyztF1w02An2tt3XcoGaGx6RQ,13951
60
60
  symai/backend/engines/search/engine_perplexity.py,sha256=yxuhGaA38d1FRbLv6piLll0QDxCCyBVK6eeomjYNryM,4157
61
61
  symai/backend/engines/search/engine_serpapi.py,sha256=UqvGHs1J9BOv05C0FJUQjbz29_VuWncIkeDwlRPUilU,3698
62
62
  symai/backend/engines/speech_to_text/engine_local_whisper.py,sha256=LRsXliCpHDFPFaE-vPky3-DLkmYwmwe2mxfF0Brz4Wg,8220
@@ -154,9 +154,9 @@ symai/ops/primitives.py,sha256=EaB2Ekx9yGNDaQa3aKS5KpuEr5awAUbO3OcBbufI-l4,11072
154
154
  symai/server/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
155
155
  symai/server/huggingface_server.py,sha256=UpSBflnQaenDjY1AAn5LUYeg5J4gJLWiMuC5DcoIV3E,8743
156
156
  symai/server/llama_cpp_server.py,sha256=qVCldTdcQhK2YCu7sDNSYziu1p2AQieqMFfY028-yOc,2049
157
- symbolicai-0.20.0.dist-info/licenses/LICENSE,sha256=9vRFudlJ1ghVfra5lcCUIYQCqnZSYcBLjLHbGRsrQCs,1505
158
- symbolicai-0.20.0.dist-info/METADATA,sha256=GCSYoBz8Aq53_FepJL3fxhmhb1hh-E4G9AcawG5FOqk,23122
159
- symbolicai-0.20.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
160
- symbolicai-0.20.0.dist-info/entry_points.txt,sha256=JV5sdydIfUZdDF6QBEQHiZHod6XNPjCjpWQrXh7gTAw,261
161
- symbolicai-0.20.0.dist-info/top_level.txt,sha256=bOoIDfpDIvCQtQgXcwVKJvxAKwsxpxo2IL4z92rNJjw,6
162
- symbolicai-0.20.0.dist-info/RECORD,,
157
+ symbolicai-0.20.1.dist-info/licenses/LICENSE,sha256=9vRFudlJ1ghVfra5lcCUIYQCqnZSYcBLjLHbGRsrQCs,1505
158
+ symbolicai-0.20.1.dist-info/METADATA,sha256=Lg6BX-_4lfl9afWX09E9uuvyenffX8Y4Qwkb5zh_ZKc,23122
159
+ symbolicai-0.20.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
160
+ symbolicai-0.20.1.dist-info/entry_points.txt,sha256=JV5sdydIfUZdDF6QBEQHiZHod6XNPjCjpWQrXh7gTAw,261
161
+ symbolicai-0.20.1.dist-info/top_level.txt,sha256=bOoIDfpDIvCQtQgXcwVKJvxAKwsxpxo2IL4z92rNJjw,6
162
+ symbolicai-0.20.1.dist-info/RECORD,,