alita-sdk 0.3.457__py3-none-any.whl → 0.3.486__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 alita-sdk might be problematic. Click here for more details.

Files changed (102) hide show
  1. alita_sdk/cli/__init__.py +10 -0
  2. alita_sdk/cli/__main__.py +17 -0
  3. alita_sdk/cli/agent/__init__.py +5 -0
  4. alita_sdk/cli/agent/default.py +258 -0
  5. alita_sdk/cli/agent_executor.py +155 -0
  6. alita_sdk/cli/agent_loader.py +194 -0
  7. alita_sdk/cli/agent_ui.py +228 -0
  8. alita_sdk/cli/agents.py +3592 -0
  9. alita_sdk/cli/callbacks.py +647 -0
  10. alita_sdk/cli/cli.py +168 -0
  11. alita_sdk/cli/config.py +306 -0
  12. alita_sdk/cli/context/__init__.py +30 -0
  13. alita_sdk/cli/context/cleanup.py +198 -0
  14. alita_sdk/cli/context/manager.py +731 -0
  15. alita_sdk/cli/context/message.py +285 -0
  16. alita_sdk/cli/context/strategies.py +289 -0
  17. alita_sdk/cli/context/token_estimation.py +127 -0
  18. alita_sdk/cli/formatting.py +182 -0
  19. alita_sdk/cli/input_handler.py +419 -0
  20. alita_sdk/cli/inventory.py +1256 -0
  21. alita_sdk/cli/mcp_loader.py +315 -0
  22. alita_sdk/cli/toolkit.py +327 -0
  23. alita_sdk/cli/toolkit_loader.py +85 -0
  24. alita_sdk/cli/tools/__init__.py +43 -0
  25. alita_sdk/cli/tools/approval.py +224 -0
  26. alita_sdk/cli/tools/filesystem.py +1665 -0
  27. alita_sdk/cli/tools/planning.py +389 -0
  28. alita_sdk/cli/tools/terminal.py +414 -0
  29. alita_sdk/community/__init__.py +64 -8
  30. alita_sdk/community/inventory/__init__.py +224 -0
  31. alita_sdk/community/inventory/config.py +257 -0
  32. alita_sdk/community/inventory/enrichment.py +2137 -0
  33. alita_sdk/community/inventory/extractors.py +1469 -0
  34. alita_sdk/community/inventory/ingestion.py +3172 -0
  35. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  36. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  37. alita_sdk/community/inventory/parsers/base.py +295 -0
  38. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  39. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  40. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  41. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  42. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  43. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  44. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  45. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  46. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  47. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  48. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  49. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  50. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  51. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  52. alita_sdk/community/inventory/patterns/loader.py +348 -0
  53. alita_sdk/community/inventory/patterns/registry.py +198 -0
  54. alita_sdk/community/inventory/presets.py +535 -0
  55. alita_sdk/community/inventory/retrieval.py +1403 -0
  56. alita_sdk/community/inventory/toolkit.py +169 -0
  57. alita_sdk/community/inventory/visualize.py +1370 -0
  58. alita_sdk/configurations/bitbucket.py +0 -3
  59. alita_sdk/runtime/clients/client.py +99 -26
  60. alita_sdk/runtime/langchain/assistant.py +4 -2
  61. alita_sdk/runtime/langchain/constants.py +2 -1
  62. alita_sdk/runtime/langchain/langraph_agent.py +134 -31
  63. alita_sdk/runtime/langchain/utils.py +1 -1
  64. alita_sdk/runtime/llms/preloaded.py +2 -6
  65. alita_sdk/runtime/toolkits/__init__.py +2 -0
  66. alita_sdk/runtime/toolkits/application.py +1 -1
  67. alita_sdk/runtime/toolkits/mcp.py +46 -36
  68. alita_sdk/runtime/toolkits/planning.py +171 -0
  69. alita_sdk/runtime/toolkits/tools.py +39 -6
  70. alita_sdk/runtime/tools/function.py +17 -5
  71. alita_sdk/runtime/tools/llm.py +249 -14
  72. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  73. alita_sdk/runtime/tools/planning/models.py +246 -0
  74. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  75. alita_sdk/runtime/tools/vectorstore_base.py +41 -6
  76. alita_sdk/runtime/utils/mcp_oauth.py +80 -0
  77. alita_sdk/runtime/utils/streamlit.py +6 -10
  78. alita_sdk/runtime/utils/toolkit_utils.py +19 -4
  79. alita_sdk/tools/__init__.py +54 -27
  80. alita_sdk/tools/ado/repos/repos_wrapper.py +1 -2
  81. alita_sdk/tools/base_indexer_toolkit.py +150 -19
  82. alita_sdk/tools/bitbucket/__init__.py +2 -2
  83. alita_sdk/tools/chunkers/__init__.py +3 -1
  84. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +95 -6
  85. alita_sdk/tools/chunkers/universal_chunker.py +269 -0
  86. alita_sdk/tools/code_indexer_toolkit.py +55 -22
  87. alita_sdk/tools/elitea_base.py +86 -21
  88. alita_sdk/tools/jira/__init__.py +1 -1
  89. alita_sdk/tools/jira/api_wrapper.py +91 -40
  90. alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
  91. alita_sdk/tools/qtest/__init__.py +1 -1
  92. alita_sdk/tools/qtest/api_wrapper.py +871 -32
  93. alita_sdk/tools/sharepoint/api_wrapper.py +22 -2
  94. alita_sdk/tools/sharepoint/authorization_helper.py +17 -1
  95. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +8 -2
  96. alita_sdk/tools/zephyr_essential/api_wrapper.py +12 -13
  97. {alita_sdk-0.3.457.dist-info → alita_sdk-0.3.486.dist-info}/METADATA +146 -2
  98. {alita_sdk-0.3.457.dist-info → alita_sdk-0.3.486.dist-info}/RECORD +102 -40
  99. alita_sdk-0.3.486.dist-info/entry_points.txt +2 -0
  100. {alita_sdk-0.3.457.dist-info → alita_sdk-0.3.486.dist-info}/WHEEL +0 -0
  101. {alita_sdk-0.3.457.dist-info → alita_sdk-0.3.486.dist-info}/licenses/LICENSE +0 -0
  102. {alita_sdk-0.3.457.dist-info → alita_sdk-0.3.486.dist-info}/top_level.txt +0 -0
@@ -453,41 +453,63 @@ class JiraApiWrapper(NonCodeIndexerToolkit):
453
453
  return super().validate_toolkit(values)
454
454
 
455
455
  def _parse_issues(self, issues: Dict) -> List[dict]:
456
- parsed = []
457
- for issue in issues["issues"]:
458
- if len(parsed) >= self.limit:
456
+ parsed: List[dict] = []
457
+ issues_list = issues.get("issues") if isinstance(issues, dict) else None
458
+ if not isinstance(issues_list, list):
459
+ return parsed
460
+
461
+ for issue in issues_list:
462
+ if self.limit and len(parsed) >= self.limit:
459
463
  break
460
- issue_fields = issue["fields"]
461
- key = issue["key"]
462
- id = issue["id"]
463
- summary = issue_fields["summary"]
464
- description = issue_fields["description"]
465
- created = issue_fields["created"][0:10]
466
- updated = issue_fields["updated"]
467
- duedate = issue_fields["duedate"]
468
- priority = issue_fields["priority"]["name"]
469
- status = issue_fields["status"]["name"]
470
- project_id = issue_fields["project"]["id"]
471
- issue_url = f"{self._client.url}browse/{key}"
472
- try:
473
- assignee = issue_fields["assignee"]["displayName"]
474
- except Exception:
475
- assignee = "None"
464
+
465
+ issue_fields = issue.get("fields") or {}
466
+ key = issue.get("key", "")
467
+ issue_id = issue.get("id", "")
468
+
469
+ summary = issue_fields.get("summary") or ""
470
+ description = issue_fields.get("description") or ""
471
+ created_raw = issue_fields.get("created") or ""
472
+ created = created_raw[:10] if created_raw else ""
473
+ updated = issue_fields.get("updated") or ""
474
+ duedate = issue_fields.get("duedate")
475
+
476
+ priority_info = issue_fields.get("priority") or {}
477
+ priority = priority_info.get("name") or "None"
478
+
479
+ status_info = issue_fields.get("status") or {}
480
+ status = status_info.get("name") or "Unknown"
481
+
482
+ project_info = issue_fields.get("project") or {}
483
+ project_id = project_info.get("id") or ""
484
+
485
+ issue_url = f"{self._client.url}browse/{key}" if key else self._client.url
486
+
487
+ assignee_info = issue_fields.get("assignee") or {}
488
+ assignee = assignee_info.get("displayName") or "None"
489
+
476
490
  rel_issues = {}
477
- for related_issue in issue_fields["issuelinks"]:
478
- if "inwardIssue" in related_issue.keys():
479
- rel_type = related_issue["type"]["inward"]
480
- rel_key = related_issue["inwardIssue"]["key"]
491
+ for related_issue in issue_fields.get("issuelinks") or []:
492
+ rel_type = None
493
+ rel_key = None
494
+ if related_issue.get("inwardIssue"):
495
+ rel_type = related_issue.get("type", {}).get("inward")
496
+ rel_key = related_issue["inwardIssue"].get("key")
481
497
  # rel_summary = related_issue["inwardIssue"]["fields"]["summary"]
482
- if "outwardIssue" in related_issue.keys():
483
- rel_type = related_issue["type"]["outward"]
484
- rel_key = related_issue["outwardIssue"]["key"]
498
+ elif related_issue.get("outwardIssue"):
499
+ rel_type = related_issue.get("type", {}).get("outward")
500
+ rel_key = related_issue["outwardIssue"].get("key")
485
501
  # rel_summary = related_issue["outwardIssue"]["fields"]["summary"]
486
- rel_issues = {"type": rel_type, "key": rel_key, "url": f"{self._client.url}browse/{rel_key}"}
502
+
503
+ if rel_type and rel_key:
504
+ rel_issues = {
505
+ "type": rel_type,
506
+ "key": rel_key,
507
+ "url": f"{self._client.url}browse/{rel_key}",
508
+ }
487
509
 
488
510
  parsed_issue = {
489
511
  "key": key,
490
- "id": id,
512
+ "id": issue_id,
491
513
  "projectId": project_id,
492
514
  "summary": summary,
493
515
  "description": description,
@@ -500,10 +522,13 @@ class JiraApiWrapper(NonCodeIndexerToolkit):
500
522
  "url": issue_url,
501
523
  "related_issues": rel_issues,
502
524
  }
503
- for field in self.additional_fields:
504
- field_value = issue_fields.get(field, None)
525
+
526
+ for field in (self.additional_fields or []):
527
+ field_value = issue_fields.get(field)
505
528
  parsed_issue[field] = field_value
529
+
506
530
  parsed.append(parsed_issue)
531
+
507
532
  return parsed
508
533
 
509
534
  @staticmethod
@@ -749,13 +774,24 @@ class JiraApiWrapper(NonCodeIndexerToolkit):
749
774
 
750
775
  attachment_data = []
751
776
  attachments = self._client.get_attachments_ids_from_issue(issue=jira_issue_key)
777
+ api_version = str(getattr(self._client, "api_version", "2"))
752
778
  for attachment in attachments:
753
779
  if attachment_pattern and not re.search(attachment_pattern, attachment['filename']):
754
780
  logger.info(f"Skipping attachment {attachment['filename']} as it does not match pattern {attachment_pattern}")
755
781
  continue
756
782
  logger.info(f"Processing attachment {attachment['filename']} with ID {attachment['attachment_id']}")
757
783
  try:
758
- attachment_content = self._client.get_attachment_content(attachment['attachment_id'])
784
+ attachment_content = None
785
+
786
+ # Cloud (REST v3) attachments require signed URLs returned from metadata
787
+ if api_version in {"3", "latest"} or self.cloud:
788
+ attachment_content = self._download_attachment_v3(
789
+ attachment['attachment_id'],
790
+ attachment['filename']
791
+ )
792
+
793
+ if attachment_content is None:
794
+ attachment_content = self._client.get_attachment_content(attachment['attachment_id'])
759
795
  except Exception as e:
760
796
  logger.error(
761
797
  f"Failed to download attachment {attachment['filename']} for issue {jira_issue_key}: {str(e)}")
@@ -797,15 +833,6 @@ class JiraApiWrapper(NonCodeIndexerToolkit):
797
833
  logger.debug(response_string)
798
834
  return response_string
799
835
 
800
- def _extract_attachment_content(self, attachment):
801
- """Extract attachment's content if possible (used for api v.2)"""
802
-
803
- try:
804
- content = self._client.get(attachment['content'].replace(self.base_url, ''))
805
- except Exception as e:
806
- content = f"Unable to parse content of '{attachment['filename']}' due to: {str(e)}"
807
- return f"filename: {attachment['filename']}\ncontent: {content}"
808
-
809
836
  # Helper functions for image processing
810
837
  @staticmethod
811
838
  def _collect_context_for_image(content: str, image_marker: str, context_radius: int = 500) -> str:
@@ -1038,6 +1065,30 @@ class JiraApiWrapper(NonCodeIndexerToolkit):
1038
1065
  logger.error(f"Error downloading attachment: {str(e)}")
1039
1066
  return None
1040
1067
 
1068
+ def _download_attachment_v3(self, attachment_id: str, filename: str | None = None) -> Optional[bytes]:
1069
+ """Download Jira attachment using metadata content URL (required for REST v3 / Cloud)."""
1070
+ try:
1071
+ metadata = self._client.get_attachment(attachment_id)
1072
+ except Exception as e:
1073
+ logger.error(f"Failed to retrieve metadata for attachment {attachment_id}: {str(e)}")
1074
+ return None
1075
+
1076
+ download_url = metadata.get('content') or metadata.get('_links', {}).get('content')
1077
+
1078
+ if not download_url:
1079
+ logger.warning(
1080
+ f"Attachment {attachment_id} ({filename}) metadata does not include a content URL; falling back.")
1081
+ return None
1082
+
1083
+ logger.info(f"Downloading attachment {attachment_id} via metadata content URL (v3).")
1084
+ content = self._download_attachment(download_url)
1085
+
1086
+ if content is None:
1087
+ logger.error(
1088
+ f"Failed to download attachment {attachment_id} ({filename}) from v3 content URL: {download_url}")
1089
+
1090
+ return content
1091
+
1041
1092
  def _extract_image_data(self, field_data):
1042
1093
  """
1043
1094
  Extracts image data from general JSON response.
@@ -7,6 +7,7 @@ from alita_sdk.tools.base_indexer_toolkit import BaseIndexerToolkit
7
7
 
8
8
  class NonCodeIndexerToolkit(BaseIndexerToolkit):
9
9
  def _get_indexed_data(self, index_name: str):
10
+ self._ensure_vectorstore_initialized()
10
11
  if not self.vector_adapter:
11
12
  raise ToolException("Vector adapter is not initialized. "
12
13
  "Check your configuration: embedding_model and vectorstore_type.")
@@ -37,7 +37,7 @@ class QtestToolkit(BaseToolkit):
37
37
  name,
38
38
  qtest_configuration=(QtestConfiguration, Field(description="QTest API token", json_schema_extra={
39
39
  'configuration_types': ['qtest']})),
40
- qtest_project_id=(int, Field(default=None, description="QTest project id")),
40
+ qtest_project_id=(int, Field(description="QTest project id")),
41
41
  no_of_tests_shown_in_dql_search=(Optional[int], Field(description="Max number of items returned by dql search",
42
42
  default=10)),
43
43