chunksilo 2.1.2__py3-none-any.whl → 2.1.3__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 chunksilo might be problematic. Click here for more details.

chunksilo/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  """ChunkSilo - Local RAG-based semantic document search."""
3
3
 
4
- __version__ = "2.1.2"
4
+ __version__ = "2.1.3"
chunksilo/search.py CHANGED
@@ -389,8 +389,8 @@ def _prepare_jira_jql_query(query: str, config: dict[str, Any]) -> str:
389
389
  """Construct a JQL query from user search terms and configuration.
390
390
 
391
391
  Uses Jira's 'text' field which searches across Summary, Description,
392
- Environment, Comments, and all text custom fields. This provides broad
393
- coverage similar to natural language search.
392
+ Environment, Comments, and all text custom fields. Additionally detects
393
+ Jira issue keys (e.g., "ABEI-1660") and includes exact key searches.
394
394
 
395
395
  Note: Fuzzy search operators (~) are deprecated in Jira Cloud but work
396
396
  in Data Center/Server. ChunkSilo's semantic search (embeddings + reranker)
@@ -414,20 +414,35 @@ def _prepare_jira_jql_query(query: str, config: dict[str, Any]) -> str:
414
414
  References:
415
415
  - Jira text field: https://support.atlassian.com/jira-software-cloud/docs/search-for-work-items-using-the-text-field/
416
416
  - JQL operators: https://support.atlassian.com/jira-software-cloud/docs/jql-operators/
417
+ - JQL key field: https://support.atlassian.com/jira-software-cloud/docs/search-by-issue-key/
417
418
  """
419
+ # Detect Jira issue keys in the query (e.g., "ABEI-1660", "PROJ-123")
420
+ # Pattern matches: 1+ uppercase letters/digits, hyphen, 1+ digits
421
+ # Case-insensitive matching, but preserve original case for extraction
422
+ issue_key_pattern = r'\b([A-Z][A-Z0-9]+-\d+)\b'
423
+ detected_keys = re.findall(issue_key_pattern, query, re.IGNORECASE)
424
+
425
+ # Build key search clauses for exact issue key matches
426
+ key_clauses = []
427
+ if detected_keys:
428
+ # Normalize to uppercase (Jira keys are case-insensitive)
429
+ unique_keys = list(dict.fromkeys(k.upper() for k in detected_keys))
430
+ key_clauses = [f'key = "{key}"' for key in unique_keys]
431
+ logger.debug(f"Detected Jira issue keys in query: {unique_keys}")
432
+
418
433
  # Reuse Confluence query term preparation for stopword filtering
419
434
  # This gives us a clean list of meaningful search terms
420
435
  query_terms = _prepare_confluence_query_terms(query)
421
436
 
422
437
  # Build the text search clause
423
438
  # Using JQL 'text' field which searches across all text fields for broad recall
439
+ text_clause = ""
424
440
  if not query_terms:
425
441
  # No meaningful terms after filtering, use original query
426
442
  escaped = query.strip().replace('"', '\\"')
427
- if not escaped:
428
- logger.warning("Jira search skipped: empty query after processing")
429
- return ""
430
- text_clause = f'text ~ "{escaped}"'
443
+ if escaped and not detected_keys:
444
+ # Only add text clause if we don't have issue keys
445
+ text_clause = f'text ~ "{escaped}"'
431
446
  elif len(query_terms) == 1:
432
447
  # Single term - simple text search
433
448
  text_clause = f'text ~ "{query_terms[0]}"'
@@ -437,6 +452,21 @@ def _prepare_jira_jql_query(query: str, config: dict[str, Any]) -> str:
437
452
  text_conditions = ' OR '.join([f'text ~ "{term}"' for term in query_terms])
438
453
  text_clause = f'({text_conditions})'
439
454
 
455
+ # Combine key and text searches
456
+ if key_clauses and text_clause:
457
+ # Search both by key and text content
458
+ combined_clause = f'({" OR ".join(key_clauses)} OR {text_clause})'
459
+ elif key_clauses:
460
+ # Only key searches
461
+ combined_clause = " OR ".join(key_clauses)
462
+ elif text_clause:
463
+ # Only text search
464
+ combined_clause = text_clause
465
+ else:
466
+ # No valid search terms
467
+ logger.warning("Jira search skipped: empty query after processing")
468
+ return ""
469
+
440
470
  # Add project filter if configured
441
471
  # Empty projects list means search all accessible projects
442
472
  projects = config["jira"].get("projects", [])
@@ -444,9 +474,9 @@ def _prepare_jira_jql_query(query: str, config: dict[str, Any]) -> str:
444
474
  # Restrict search to specific project keys
445
475
  project_list = ", ".join([f'"{p}"' for p in projects])
446
476
  project_clause = f'project IN ({project_list})'
447
- jql = f'{text_clause} AND {project_clause}'
477
+ jql = f'{combined_clause} AND {project_clause}'
448
478
  else:
449
- jql = text_clause
479
+ jql = combined_clause
450
480
 
451
481
  # Order by updated DESC for recency
452
482
  # This enables ChunkSilo's recency boost feature and returns most relevant recent issues first
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chunksilo
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Local RAG-based semantic document search with MCP server interface
5
5
  Author: Fredrik Reveny
6
6
  License-Expression: Apache-2.0
@@ -1,15 +1,15 @@
1
- chunksilo/__init__.py,sha256=GrNevQaJPoOU-nJcoPzc9Xj2B0hA4FFyX3s9n5MbpuI,121
1
+ chunksilo/__init__.py,sha256=nTojkFpcudPYQkEmwmrpjHokGO-KkWu5c1rYqgElV4Q,121
2
2
  chunksilo/__main__.py,sha256=eY8-KfJfBz0nibDPY_jv2RvkLXEx7ZDSPRWiDJb7PpY,39
3
3
  chunksilo/cfgload.py,sha256=dvzDSftqbLCEhYb76OPA4hP_ToJE7FYdpko67m_2RkA,4639
4
4
  chunksilo/cli.py,sha256=ZKXzW-HOmnLXC4Ynu-D86XIbp7bdQ_OYVHuHFVlj41U,4170
5
5
  chunksilo/confluence_html_formatter.py,sha256=D8pb5TCrai6exIqeajH49y4D_t0jfQkmI6aNm4BzPIg,2828
6
6
  chunksilo/index.py,sha256=ECSTH8c0ZhnTxAHxM7dcCfFOGTk99STHuyDhc3uMCO0,51618
7
- chunksilo/search.py,sha256=Xj39JQ6eglto5Jfe9FKVWY_vo3sJaMndGvbcFR2_Ca4,49779
7
+ chunksilo/search.py,sha256=58PGC2I3pIXE5_OoZXjDMs7-WLez3Y6XcvJPhU1QR8U,51162
8
8
  chunksilo/server.py,sha256=PhQWMvEGb3UqWwk0tm44kTOnKH2NH4NmshnKx11xwh8,3374
9
- chunksilo-2.1.2.dist-info/licenses/LICENSE,sha256=kda7NTahQy3nKvLe-LGIVCdI-qePTyqNNx2e6HLVH3k,10766
10
- chunksilo-2.1.2.dist-info/licenses/NOTICE,sha256=58GCfasR-XT7RPvz9OoWb4NrPg-3AqEwzw9FJOhngZo,1228
11
- chunksilo-2.1.2.dist-info/METADATA,sha256=KPo1HOnSaCqmd2K0KAJZSOf2pbxZWkbhzz7hx-tE2w0,13789
12
- chunksilo-2.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
- chunksilo-2.1.2.dist-info/entry_points.txt,sha256=TfgrfBQyIRHMG5NFaXR-owDLsjHBCxjJ4YGIGBnVzbQ,87
14
- chunksilo-2.1.2.dist-info/top_level.txt,sha256=xfAH0GhTfZbwkbi_DgUA5keNP-osqVNcoZjwkhpwVms,10
15
- chunksilo-2.1.2.dist-info/RECORD,,
9
+ chunksilo-2.1.3.dist-info/licenses/LICENSE,sha256=kda7NTahQy3nKvLe-LGIVCdI-qePTyqNNx2e6HLVH3k,10766
10
+ chunksilo-2.1.3.dist-info/licenses/NOTICE,sha256=58GCfasR-XT7RPvz9OoWb4NrPg-3AqEwzw9FJOhngZo,1228
11
+ chunksilo-2.1.3.dist-info/METADATA,sha256=Z2sU8Kq--K3G_r72deuf_mPifVTcl5i21W1nWY-CoUw,13789
12
+ chunksilo-2.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ chunksilo-2.1.3.dist-info/entry_points.txt,sha256=TfgrfBQyIRHMG5NFaXR-owDLsjHBCxjJ4YGIGBnVzbQ,87
14
+ chunksilo-2.1.3.dist-info/top_level.txt,sha256=xfAH0GhTfZbwkbi_DgUA5keNP-osqVNcoZjwkhpwVms,10
15
+ chunksilo-2.1.3.dist-info/RECORD,,