MindsDB 25.5.4.0__py3-none-any.whl → 25.5.4.2__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 MindsDB might be problematic. Click here for more details.

mindsdb/__about__.py CHANGED
@@ -1,10 +1,10 @@
1
- __title__ = 'MindsDB'
2
- __package_name__ = 'mindsdb'
3
- __version__ = '25.5.4.0'
1
+ __title__ = "MindsDB"
2
+ __package_name__ = "mindsdb"
3
+ __version__ = "25.5.4.2"
4
4
  __description__ = "MindsDB's AI SQL Server enables developers to build AI tools that need access to real-time data to perform their tasks"
5
5
  __email__ = "jorge@mindsdb.com"
6
- __author__ = 'MindsDB Inc'
7
- __github__ = 'https://github.com/mindsdb/mindsdb'
8
- __pypi__ = 'https://pypi.org/project/mindsdb/'
9
- __license__ = 'Elastic License 2.0'
10
- __copyright__ = 'Copyright(c) 2018 MindsDB, Inc'
6
+ __author__ = "MindsDB Inc"
7
+ __github__ = "https://github.com/mindsdb/mindsdb"
8
+ __pypi__ = "https://pypi.org/project/mindsdb/"
9
+ __license__ = "Elastic License 2.0"
10
+ __copyright__ = "Copyright(c) 2018 MindsDB, Inc"
@@ -4,15 +4,15 @@ import click
4
4
  from dotenv import load_dotenv
5
5
 
6
6
  # A2A specific imports
7
- from .common.types import (
7
+ from mindsdb.api.a2a.common.types import (
8
8
  AgentCard,
9
9
  AgentCapabilities,
10
10
  AgentSkill,
11
11
  MissingAPIKeyError,
12
12
  )
13
- from .common.server.server import A2AServer
14
- from .task_manager import AgentTaskManager
15
- from .agent import MindsDBAgent
13
+ from mindsdb.api.a2a.common.server.server import A2AServer
14
+ from mindsdb.api.a2a.task_manager import AgentTaskManager
15
+ from mindsdb.api.a2a.agent import MindsDBAgent
16
16
 
17
17
  logger = logging.getLogger(__name__)
18
18
  logging.basicConfig(
@@ -73,10 +73,7 @@ def main(
73
73
 
74
74
  agent_card = AgentCard(
75
75
  name="MindsDB Agent Connector",
76
- description=(
77
- "A2A connector that proxies requests to MindsDB agents "
78
- f"in project '{project_name}'."
79
- ),
76
+ description=(f"A2A connector that proxies requests to MindsDB agents in project '{project_name}'."),
80
77
  url=f"http://{host}:{port}",
81
78
  version="1.0.0",
82
79
  defaultInputModes=MindsDBAgent.SUPPORTED_CONTENT_TYPES,
@@ -110,5 +107,38 @@ def main(
110
107
  sys.exit(1)
111
108
 
112
109
 
110
+ # This function is called by mindsdb/api/a2a/run_a2a.py
111
+ def main_with_config(config=None, *args, **kwargs):
112
+ """
113
+ Alternative entry point that accepts configuration as a dictionary.
114
+ This is used when A2A is started as a subprocess of the main MindsDB process.
115
+
116
+ Args:
117
+ config (dict): Configuration dictionary
118
+ args: Additional positional arguments
119
+ kwargs: Additional keyword arguments
120
+ """
121
+ if config is None:
122
+ config = {}
123
+
124
+ # Extract configuration values with fallbacks to default values
125
+ host = config.get("host", "localhost")
126
+ port = int(config.get("port", 47338))
127
+ mindsdb_host = config.get("mindsdb_host", "localhost")
128
+ mindsdb_port = int(config.get("mindsdb_port", 47334))
129
+ project_name = config.get("project_name", "mindsdb")
130
+ log_level = config.get("log_level", "INFO")
131
+
132
+ # Call the main function with the extracted configuration
133
+ main.callback(
134
+ host=host,
135
+ port=port,
136
+ mindsdb_host=mindsdb_host,
137
+ mindsdb_port=mindsdb_port,
138
+ project_name=project_name,
139
+ log_level=log_level,
140
+ )
141
+
142
+
113
143
  if __name__ == "__main__":
114
144
  main()
@@ -6,9 +6,7 @@ from dotenv import load_dotenv
6
6
  from typing import Dict, Any, Optional
7
7
 
8
8
  # Configure logging
9
- logging.basicConfig(
10
- level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
11
- )
9
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
12
10
  logger = logging.getLogger(__name__)
13
11
 
14
12
 
@@ -22,9 +20,7 @@ def setup_python_path():
22
20
  this_file_dir = os.path.dirname(os.path.abspath(__file__))
23
21
 
24
22
  # Walk three levels up: a2a/ -> api/ -> mindsdb/ -> <repo_root>
25
- repo_root = os.path.abspath(
26
- os.path.join(this_file_dir, os.pardir, os.pardir, os.pardir)
27
- )
23
+ repo_root = os.path.abspath(os.path.join(this_file_dir, os.pardir, os.pardir, os.pardir))
28
24
 
29
25
  # Prepend to PYTHONPATH if not already present
30
26
  if repo_root not in sys.path:
@@ -54,65 +50,26 @@ def main(config_override: Optional[Dict[str, Any]] = None, *args, **kwargs):
54
50
  load_dotenv()
55
51
 
56
52
  try:
57
- # Import the main function from __main__.py
58
- from mindsdb.api.a2a.__main__ import main as a2a_main
53
+ # Import the main_with_config function from __main__.py
54
+ from mindsdb.api.a2a.__main__ import main_with_config
59
55
  from mindsdb.utilities.config import config
60
56
 
61
57
  logger.info("Successfully imported a2a module")
62
58
 
63
59
  # Get configuration from config system or use provided override
64
- a2a_config = config_override if config_override is not None else config.get('a2a', {})
60
+ a2a_config = config_override if config_override is not None else config.get("api", {}).get("a2a", {})
65
61
 
66
62
  # Set log level if specified
67
- if a2a_config.get('log_level'):
68
- log_level = getattr(logging, a2a_config['log_level'].upper(), None)
63
+ if a2a_config.get("log_level"):
64
+ log_level = getattr(logging, a2a_config["log_level"].upper(), None)
69
65
  if log_level:
70
66
  logger.setLevel(log_level)
71
67
  logger.info(f"Set log level to {a2a_config['log_level'].upper()}")
72
68
 
73
- # Prepare command line arguments based on configuration
74
- sys_argv = [] # Start with an empty list instead of copying sys.argv
69
+ logger.info(f"Starting A2A with configuration: {a2a_config}")
75
70
 
76
- # Only add args that aren't already in sys.argv
77
- if a2a_config.get('host'):
78
- sys_argv.extend(['--host', a2a_config['host']])
79
-
80
- if a2a_config.get('port'):
81
- sys_argv.extend(['--port', str(a2a_config['port'])])
82
-
83
- if a2a_config.get('mindsdb_host'):
84
- sys_argv.extend(['--mindsdb-host', a2a_config['mindsdb_host']])
85
-
86
- if a2a_config.get('mindsdb_port'):
87
- sys_argv.extend(['--mindsdb-port', str(a2a_config['mindsdb_port'])])
88
-
89
- if a2a_config.get('project_name'):
90
- sys_argv.extend(['--project-name', a2a_config['project_name']])
91
-
92
- if a2a_config.get('log_level'):
93
- sys_argv.extend(['--log-level', a2a_config['log_level']])
94
-
95
- logger.info(f"Starting A2A with arguments: {' '.join(sys_argv)}")
96
-
97
- # Temporarily replace sys.argv with our constructed arguments
98
- original_argv = sys.argv
99
- sys.argv = [sys.argv[0]] + sys_argv
100
-
101
- # Run the main function with the configured arguments
102
- a2a_args = []
103
- for arg in sys_argv:
104
- # Skip the --api argument and its value
105
- if arg.startswith('--api=') or arg == '--api':
106
- continue
107
- # Skip the value of --api if the previous arg was --api
108
- if arg.startswith('--') and sys_argv[sys_argv.index(arg) - 1] == '--api':
109
- continue
110
- a2a_args.append(arg)
111
-
112
- a2a_main(a2a_args)
113
-
114
- # Restore original sys.argv
115
- sys.argv = original_argv
71
+ # Call the main_with_config function with the configuration
72
+ main_with_config(a2a_config, *args, **kwargs)
116
73
 
117
74
  except ImportError as e:
118
75
  logger.error(f"Error importing a2a module: {e}")
@@ -1,5 +1,5 @@
1
1
  from typing import AsyncIterable
2
- from .common.types import (
2
+ from mindsdb.api.a2a.common.types import (
3
3
  SendTaskRequest,
4
4
  TaskSendParams,
5
5
  Message,
@@ -16,8 +16,8 @@ from .common.types import (
16
16
  SendTaskStreamingResponse,
17
17
  InvalidRequestError,
18
18
  )
19
- from .common.server.task_manager import InMemoryTaskManager
20
- from .agent import MindsDBAgent
19
+ from mindsdb.api.a2a.common.server.task_manager import InMemoryTaskManager
20
+ from mindsdb.api.a2a.agent import MindsDBAgent
21
21
 
22
22
  from typing import Union
23
23
  import logging
@@ -27,7 +27,6 @@ logger = logging.getLogger(__name__)
27
27
 
28
28
 
29
29
  class AgentTaskManager(InMemoryTaskManager):
30
-
31
30
  def __init__(
32
31
  self,
33
32
  project_name: str,
@@ -46,9 +45,7 @@ class AgentTaskManager(InMemoryTaskManager):
46
45
  def _create_agent(self, agent_name: str = None) -> MindsDBAgent:
47
46
  """Create a new MindsDBAgent instance for the given agent name."""
48
47
  if not agent_name:
49
- raise ValueError(
50
- "Agent name is required but was not provided in the request"
51
- )
48
+ raise ValueError("Agent name is required but was not provided in the request")
52
49
 
53
50
  return MindsDBAgent(
54
51
  agent_name=agent_name,
@@ -57,9 +54,7 @@ class AgentTaskManager(InMemoryTaskManager):
57
54
  port=self.mindsdb_port,
58
55
  )
59
56
 
60
- async def _stream_generator(
61
- self, request: SendTaskStreamingRequest
62
- ) -> AsyncIterable[SendTaskStreamingResponse]:
57
+ async def _stream_generator(self, request: SendTaskStreamingRequest) -> AsyncIterable[SendTaskStreamingResponse]:
63
58
  task_send_params: TaskSendParams = request.params
64
59
  query = self._get_user_query(task_send_params)
65
60
  params = self._get_task_params(task_send_params)
@@ -112,9 +107,7 @@ class AgentTaskManager(InMemoryTaskManager):
112
107
  # Yield the artifact update
113
108
  yield SendTaskStreamingResponse(
114
109
  id=request.id,
115
- result=TaskArtifactUpdateEvent(
116
- id=task_send_params.id, artifact=artifact
117
- ),
110
+ result=TaskArtifactUpdateEvent(id=task_send_params.id, artifact=artifact),
118
111
  )
119
112
 
120
113
  # Yield the final status update
@@ -169,9 +162,7 @@ class AgentTaskManager(InMemoryTaskManager):
169
162
  # Include SQL queries
170
163
  tool_input = action.get("tool_input", "")
171
164
  if "$START$" in tool_input and "$STOP$" in tool_input:
172
- sql = tool_input.replace("$START$", "").replace(
173
- "$STOP$", ""
174
- )
165
+ sql = tool_input.replace("$START$", "").replace("$STOP$", "")
175
166
  parts.append(
176
167
  {
177
168
  "type": "text",
@@ -227,17 +218,13 @@ class AgentTaskManager(InMemoryTaskManager):
227
218
  if "metadata" in part:
228
219
  new_part["metadata"] = part["metadata"]
229
220
  else:
230
- new_part["metadata"] = {
231
- "thought_type": part.get("type", "text")
232
- }
221
+ new_part["metadata"] = {"thought_type": part.get("type", "text")}
233
222
 
234
223
  parts.append(new_part)
235
224
 
236
225
  # Try to determine the type from parts for the thought dictionary
237
226
  for part in item["parts"]:
238
- if part.get("type") == "text" and part.get(
239
- "text", ""
240
- ).startswith("$START$"):
227
+ if part.get("type") == "text" and part.get("text", "").startswith("$START$"):
241
228
  thought_dict["type"] = "sql"
242
229
  thought_dict["query"] = part.get("text")
243
230
  else:
@@ -300,9 +287,7 @@ class AgentTaskManager(InMemoryTaskManager):
300
287
  status=task_status,
301
288
  final=False,
302
289
  )
303
- yield SendTaskStreamingResponse(
304
- id=request.id, result=task_update_event
305
- )
290
+ yield SendTaskStreamingResponse(id=request.id, result=task_update_event)
306
291
 
307
292
  # If this is the final chunk, send a completion message
308
293
  if is_task_complete:
@@ -311,13 +296,9 @@ class AgentTaskManager(InMemoryTaskManager):
311
296
  task_status = TaskStatus(state=task_state)
312
297
  yield SendTaskStreamingResponse(
313
298
  id=request.id,
314
- result=TaskArtifactUpdateEvent(
315
- id=task_send_params.id, artifact=artifact
316
- ),
317
- )
318
- await self._update_store(
319
- task_send_params.id, task_status, [artifact]
299
+ result=TaskArtifactUpdateEvent(id=task_send_params.id, artifact=artifact),
320
300
  )
301
+ await self._update_store(task_send_params.id, task_status, [artifact])
321
302
  yield SendTaskStreamingResponse(
322
303
  id=request.id,
323
304
  result=TaskStatusUpdateEvent(
@@ -338,9 +319,7 @@ class AgentTaskManager(InMemoryTaskManager):
338
319
  artifact = Artifact(parts=parts, index=0, append=False)
339
320
  yield SendTaskStreamingResponse(
340
321
  id=request.id,
341
- result=TaskArtifactUpdateEvent(
342
- id=task_send_params.id, artifact=artifact
343
- ),
322
+ result=TaskArtifactUpdateEvent(id=task_send_params.id, artifact=artifact),
344
323
  )
345
324
 
346
325
  # Then mark the task as completed with an error
@@ -415,10 +394,7 @@ class AgentTaskManager(InMemoryTaskManager):
415
394
  )
416
395
 
417
396
  # Check if the message has metadata
418
- if (
419
- not hasattr(request.params.message, "metadata")
420
- or not request.params.message.metadata
421
- ):
397
+ if not hasattr(request.params.message, "metadata") or not request.params.message.metadata:
422
398
  return JSONRPCResponse(
423
399
  id=request.id,
424
400
  error=InvalidRequestError(message="Missing metadata in message"),
@@ -462,14 +438,10 @@ class AgentTaskManager(InMemoryTaskManager):
462
438
  logger.error(f"Error in on_send_task_subscribe: {str(e)}")
463
439
  yield SendTaskStreamingResponse(
464
440
  id=request.id,
465
- error=InternalError(
466
- message=f"Error processing streaming request: {str(e)}"
467
- ),
441
+ error=InternalError(message=f"Error processing streaming request: {str(e)}"),
468
442
  )
469
443
 
470
- async def _update_store(
471
- self, task_id: str, status: TaskStatus, artifacts: list[Artifact]
472
- ) -> Task:
444
+ async def _update_store(self, task_id: str, status: TaskStatus, artifacts: list[Artifact]) -> Task:
473
445
  async with self.lock:
474
446
  try:
475
447
  task = self.tasks[task_id]
@@ -544,9 +516,7 @@ class AgentTaskManager(InMemoryTaskManager):
544
516
  # For streaming mode, we'll use the streaming endpoint instead
545
517
  # Just create a minimal response to acknowledge the request
546
518
  task_state = TaskState.WORKING
547
- task = await self._update_store(
548
- task_send_params.id, TaskStatus(state=task_state), []
549
- )
519
+ task = await self._update_store(task_send_params.id, TaskStatus(state=task_state), [])
550
520
  return SendTaskResponse(id=request.id, result=task)
551
521
  else:
552
522
  # For non-streaming mode, collect all chunks into a single response
@@ -571,9 +541,7 @@ class AgentTaskManager(InMemoryTaskManager):
571
541
  task_send_params.id,
572
542
  TaskStatus(
573
543
  state=task_state,
574
- message=Message(
575
- role="agent", parts=all_parts, metadata=final_metadata
576
- ),
544
+ message=Message(role="agent", parts=all_parts, metadata=final_metadata),
577
545
  ),
578
546
  [Artifact(parts=all_parts)],
579
547
  )
@@ -586,9 +554,7 @@ class AgentTaskManager(InMemoryTaskManager):
586
554
  task_state = TaskState.FAILED
587
555
  task = await self._update_store(
588
556
  task_send_params.id,
589
- TaskStatus(
590
- state=task_state, message=Message(role="agent", parts=parts)
591
- ),
557
+ TaskStatus(state=task_state, message=Message(role="agent", parts=parts)),
592
558
  [Artifact(parts=parts)],
593
559
  )
594
560
  return SendTaskResponse(id=request.id, result=task)