lollms-client 0.25.0__py3-none-any.whl → 0.25.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.

Potentially problematic release.


This version of lollms-client might be problematic. Click here for more details.

lollms_client/__init__.py CHANGED
@@ -8,7 +8,7 @@ from lollms_client.lollms_utilities import PromptReshaper # Keep general utiliti
8
8
  from lollms_client.lollms_mcp_binding import LollmsMCPBinding, LollmsMCPBindingManager
9
9
 
10
10
 
11
- __version__ = "0.25.0" # Updated version
11
+ __version__ = "0.25.1" # Updated version
12
12
 
13
13
  # Optionally, you could define __all__ if you want to be explicit about exports
14
14
  __all__ = [
@@ -104,15 +104,15 @@ class OpenAIBinding(LollmsLLMBinding):
104
104
  """
105
105
  count = 0
106
106
  output = ""
107
+ messages = [
108
+ {
109
+ "role": "system",
110
+ "content": system_prompt or "You are a helpful assistant.",
111
+ }
112
+ ]
107
113
 
108
114
  # Prepare messages based on whether images are provided
109
115
  if images:
110
- messages = [
111
- {
112
- "role": "system",
113
- "content": system_prompt,
114
- }
115
- ]
116
116
  if split:
117
117
  messages += self.split_discussion(prompt,user_keyword=user_keyword, ai_keyword=ai_keyword)
118
118
  if images:
@@ -151,7 +151,27 @@ class OpenAIBinding(LollmsLLMBinding):
151
151
  )
152
152
 
153
153
  else:
154
- messages = [{"role": "user", "content": prompt}]
154
+
155
+ if split:
156
+ messages += self.split_discussion(prompt,user_keyword=user_keyword, ai_keyword=ai_keyword)
157
+ if images:
158
+ messages[-1]["content"] = [
159
+ {
160
+ "type": "text",
161
+ "text": messages[-1]["content"]
162
+ }
163
+ ]
164
+ else:
165
+ messages.append({
166
+ 'role': 'user',
167
+ 'content': [
168
+ {
169
+ "type": "text",
170
+ "text": prompt
171
+ }
172
+ ]
173
+ }
174
+ )
155
175
 
156
176
  # Generate text using the OpenAI API
157
177
  if self.completion_format == ELF_COMPLETION_FORMAT.Chat:
@@ -1443,7 +1443,7 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1443
1443
  use_mcps: Union[None, bool, List[str]] = None,
1444
1444
  use_data_store: Union[None, Dict[str, Callable]] = None,
1445
1445
  system_prompt: str = None,
1446
- reasoning_system_prompt: str = "You are a logical and adaptive AI assistant.",
1446
+ reasoning_system_prompt: str = "You are a logical AI assistant. Your task is to achieve the user's goal by thinking step-by-step and using the available tools.",
1447
1447
  images: Optional[List[str]] = None,
1448
1448
  max_reasoning_steps: int = None,
1449
1449
  decision_temperature: float = None,
@@ -1529,6 +1529,8 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1529
1529
  def log_prompt(prompt, type="prompt"):
1530
1530
  ASCIIColors.cyan(f"** DEBUG: {type} **")
1531
1531
  ASCIIColors.magenta(prompt[-15000:])
1532
+ prompt_size = self.count_tokens(prompt)
1533
+ ASCIIColors.red(f"Prompt size:{prompt_size}/{self.default_ctx_size}")
1532
1534
  ASCIIColors.cyan(f"** DEBUG: DONE **")
1533
1535
 
1534
1536
  # --- Define Inner Helper Functions ---
@@ -1578,9 +1580,9 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1578
1580
 
1579
1581
  # Add the new put_code_in_buffer tool definition
1580
1582
  available_tools.append({
1581
- "name": "put_code_in_buffer",
1582
- "description": "Generates a block of code (e.g., Python, SQL) to be used by another tool. It returns a unique 'code_id'. You must then use this 'code_id' as the value for the code parameter in the subsequent tool call. This **does not** execute the code. It only buffers it for future use. Only use it if another tool requires code.",
1583
- "input_schema": {"type": "object", "properties": {"prompt": {"type": "string", "description": "A detailed natural language description of the code's purpose and requirements."}}, "required": ["prompt"]}
1583
+ "name": "generate_code",
1584
+ "description": """Generates and stores code into a buffer to be used by another tool. You can put the uuid of the generated code into the fields that require long code among the tools. If no tool requires code as input do not use generate_code. generate_code do not execute the code nor does it audit it.""",
1585
+ "input_schema": {"type": "object", "properties": {"prompt": {"type": "string", "description": "A detailed natural language description of the code's purpose and requirements."}, "language": {"type": "string", "description": "The programming language of the generated code. By default it uses python."}}, "required": ["prompt"]}
1584
1586
  })
1585
1587
  # Add the new refactor_scratchpad tool definition
1586
1588
  available_tools.append({
@@ -1602,8 +1604,7 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1602
1604
  user_context = f'Original User Request: "{original_user_prompt}"'
1603
1605
  if images: user_context += f'\n(Note: {len(images)} image(s) were provided with this request.)'
1604
1606
 
1605
- reasoning_prompt_template = f"""You are a logical AI assistant. Your task is to achieve the user's goal by thinking step-by-step and using the available tools.
1606
-
1607
+ reasoning_prompt_template = f"""
1607
1608
  --- AVAILABLE TOOLS ---
1608
1609
  {formatted_tools_list}
1609
1610
  --- CONTEXT ---
@@ -1762,7 +1763,7 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1762
1763
  # --- Final Answer Synthesis ---
1763
1764
  synthesis_id = log_event("Synthesizing final answer...", MSG_TYPE.MSG_TYPE_STEP_START)
1764
1765
 
1765
- final_answer_prompt = f"""You are an AI assistant. Provide a final, comprehensive answer based on your work.
1766
+ final_answer_prompt = f"""
1766
1767
  --- Original User Request ---
1767
1768
  "{original_user_prompt}"
1768
1769
  --- Your Internal Scratchpad (Actions Taken & Findings) ---
@@ -1773,6 +1774,8 @@ Provide your response as a single JSON object inside a JSON markdown tag. Use th
1773
1774
  - Do not talk about your internal process unless it's necessary to explain why you couldn't find an answer.
1774
1775
  """
1775
1776
  if debug: log_prompt(final_answer_prompt, "FINAL ANSWER SYNTHESIS PROMPT")
1777
+
1778
+
1776
1779
  final_answer_text = self.generate_text(prompt=final_answer_prompt, system_prompt=system_prompt, images=images, stream=streaming_callback is not None, streaming_callback=streaming_callback, temperature=final_answer_temperature, **llm_generation_kwargs)
1777
1780
  final_answer = self.remove_thinking_blocks(final_answer_text)
1778
1781
  if debug: log_prompt(final_answer_text, "FINAL ANSWER RESPONSE")
@@ -423,6 +423,10 @@ class LollmsDiscussion:
423
423
  else:
424
424
  return cls(lollmsClient=lollms_client, discussion_id=kwargs.get('id'), **init_args)
425
425
 
426
+ def get_messages(self):
427
+ """Returns the list of messages"""
428
+ return self._db_discussion.messages
429
+
426
430
  def __getattr__(self, name: str) -> Any:
427
431
  """Proxies attribute getting to the underlying discussion object."""
428
432
  if name == 'metadata':
@@ -119,7 +119,26 @@ class RemoteMCPBinding(LollmsMCPBinding):
119
119
  future = asyncio.run_coroutine_threadsafe(coro, self._loop)
120
120
  return future.result(timeout)
121
121
 
122
- ### MODIFIED: Now operates on a specific server identified by alias
122
+ def _prepare_headers(self, alias: str) -> Dict[str, str]:
123
+ """Prepares the headers dictionary from the server's auth_config."""
124
+ server_info = self.servers[alias]
125
+ auth_config = server_info.get("auth_config", {})
126
+ headers = {}
127
+ auth_type = auth_config.get("type")
128
+ if auth_type == "api_key":
129
+ api_key = auth_config.get("key")
130
+ header_name = auth_config.get("header_name", "X-API-Key") # Default to X-API-Key
131
+ if api_key:
132
+ headers[header_name] = api_key
133
+ ASCIIColors.info(f"{self.binding_name}: Using API Key authentication for server '{alias}'.")
134
+
135
+ elif auth_type == "bearer": # <-- NEW BLOCK
136
+ token = auth_config.get("token")
137
+ if token:
138
+ headers["Authorization"] = f"Bearer {token}"
139
+
140
+ return headers
141
+
123
142
  async def _initialize_connection_async(self, alias: str) -> bool:
124
143
  server_info = self.servers[alias]
125
144
  if server_info["initialized"]:
@@ -128,10 +147,13 @@ class RemoteMCPBinding(LollmsMCPBinding):
128
147
  server_url = server_info["url"]
129
148
  ASCIIColors.info(f"{self.binding_name}: Initializing connection to '{alias}' ({server_url})...")
130
149
  try:
150
+ # Prepare authentication headers
151
+ auth_headers = self._prepare_headers(alias)
152
+
131
153
  exit_stack = AsyncExitStack()
132
154
 
133
155
  client_streams = await exit_stack.enter_async_context(
134
- streamablehttp_client(server_url)
156
+ streamablehttp_client(url=server_url, headers=auth_headers) # Pass the headers here
135
157
  )
136
158
  read_stream, write_stream, _ = client_streams
137
159
 
@@ -343,3 +365,59 @@ class RemoteMCPBinding(LollmsMCPBinding):
343
365
 
344
366
  def get_binding_config(self) -> Dict[str, Any]:
345
367
  return self.config
368
+
369
+
370
+ def set_auth_config(self, alias: str, auth_config: Dict[str, Any]):
371
+ """
372
+ Dynamically updates the authentication configuration for a specific server.
373
+
374
+ If a connection was already active for this server, it will be closed to force
375
+ a new connection with the new authentication details on the next call.
376
+
377
+ Args:
378
+ alias (str): The alias of the server to update (the key in servers_infos).
379
+ auth_config (Dict[str, Any]): The new authentication configuration dictionary.
380
+ Example: {"type": "bearer", "token": "new-token-here"}
381
+ """
382
+ ASCIIColors.info(f"{self.binding_name}: Updating auth_config for server '{alias}'.")
383
+
384
+ server_info = self.servers.get(alias)
385
+ if not server_info:
386
+ raise ValueError(f"Server alias '{alias}' does not exist in the configuration.")
387
+
388
+ # Update the configuration in the binding's internal state
389
+ server_info["config"]["auth_config"] = auth_config
390
+
391
+ # If the server was already initialized, its connection is now obsolete.
392
+ # We must close it and mark it as uninitialized.
393
+ if server_info["initialized"]:
394
+ ASCIIColors.warning(f"{self.binding_name}: Existing connection for '{alias}' is outdated due to new authentication. It will be reset.")
395
+ try:
396
+ # Execute the close operation asynchronously on the event loop thread
397
+ self._run_async(self._close_connection_async(alias), timeout=10.0)
398
+ except Exception as e:
399
+ ASCIIColors.error(f"{self.binding_name}: Error while closing the outdated connection for '{alias}': {e}")
400
+ # Even on error, reset the state to force a new connection attempt
401
+ server_info.update({"session": None, "exit_stack": None, "initialized": False})
402
+
403
+
404
+ # --- NEW INTERNAL HELPER METHOD ---
405
+ async def _close_connection_async(self, alias: str):
406
+ """Cleanly closes the connection for a specific server alias."""
407
+ server_info = self.servers.get(alias)
408
+ if not server_info or not server_info.get("exit_stack"):
409
+ return # Nothing to do.
410
+
411
+ ASCIIColors.info(f"{self.binding_name}: Closing connection for '{alias}'...")
412
+ try:
413
+ await server_info["exit_stack"].aclose()
414
+ except Exception as e:
415
+ trace_exception(e)
416
+ ASCIIColors.error(f"{self.binding_name}: Exception while closing the exit_stack for '{alias}': {e}")
417
+ finally:
418
+ # Reset the state for this alias, no matter what.
419
+ server_info.update({
420
+ "session": None,
421
+ "exit_stack": None,
422
+ "initialized": False
423
+ })
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lollms_client
3
- Version: 0.25.0
3
+ Version: 0.25.1
4
4
  Summary: A client library for LoLLMs generate endpoint
5
5
  Author-email: ParisNeo <parisneoai@gmail.com>
6
6
  License: Apache Software License
@@ -26,10 +26,10 @@ examples/mcp_examples/openai_mcp.py,sha256=7IEnPGPXZgYZyiES_VaUbQ6viQjenpcUxGiHE
26
26
  examples/mcp_examples/run_remote_mcp_example_v2.py,sha256=bbNn93NO_lKcFzfIsdvJJijGx2ePFTYfknofqZxMuRM,14626
27
27
  examples/mcp_examples/run_standard_mcp_example.py,sha256=GSZpaACPf3mDPsjA8esBQVUsIi7owI39ca5avsmvCxA,9419
28
28
  examples/test_local_models/local_chat.py,sha256=slakja2zaHOEAUsn2tn_VmI4kLx6luLBrPqAeaNsix8,456
29
- lollms_client/__init__.py,sha256=Oa7LTqicgM_xArVjSRh-oGxuAXBR5QimNkcCCvsO8qo,1047
29
+ lollms_client/__init__.py,sha256=Vt2zeJ4Ekn2UWxfSKbn_pjE-QGL7uwoTnbTFuFIOyUk,1047
30
30
  lollms_client/lollms_config.py,sha256=goEseDwDxYJf3WkYJ4IrLXwg3Tfw73CXV2Avg45M_hE,21876
31
- lollms_client/lollms_core.py,sha256=J6lGDhUiIS0jqY81AsLp6Nv6pLJbqlDCgxZI-1J-MNc,158724
32
- lollms_client/lollms_discussion.py,sha256=9mpEFz8UWMXrbyZonnq2nt1u5jDEgQqddHghUhSy9Yc,47516
31
+ lollms_client/lollms_core.py,sha256=m_qfzybasY61KgAPVa84tdkqJWIog9iuIZc88pQQ-vw,158842
32
+ lollms_client/lollms_discussion.py,sha256=JqKx--a6YMzL6ec6N9OD0B9oRlmkSV_KDKXjqP8291Y,47636
33
33
  lollms_client/lollms_js_analyzer.py,sha256=01zUvuO2F_lnUe_0NLxe1MF5aHE1hO8RZi48mNPv-aw,8361
34
34
  lollms_client/lollms_llm_binding.py,sha256=Kpzhs5Jx8eAlaaUacYnKV7qIq2wbME5lOEtKSfJKbpg,12161
35
35
  lollms_client/lollms_mcp_binding.py,sha256=0rK9HQCBEGryNc8ApBmtOlhKE1Yfn7X7xIQssXxS2Zc,8933
@@ -46,7 +46,7 @@ lollms_client/llm_bindings/__init__.py,sha256=9sWGpmWSSj6KQ8H4lKGCjpLYwhnVdL_2N7
46
46
  lollms_client/llm_bindings/llamacpp/__init__.py,sha256=Qj5RvsgPeHGNfb5AEwZSzFwAp4BOWjyxmm9qBNtstrc,63716
47
47
  lollms_client/llm_bindings/lollms/__init__.py,sha256=jfiCGJqMensJ7RymeGDDJOsdokEdlORpw9ND_Q30GYc,17831
48
48
  lollms_client/llm_bindings/ollama/__init__.py,sha256=QufsYqak2VlA2XGbzks8u55yNJFeDH2V35NGeZABkm8,32554
49
- lollms_client/llm_bindings/openai/__init__.py,sha256=i4T-QncGhrloslIF3zTlf6ZGJNZA43KCeFyOixD3Ums,19239
49
+ lollms_client/llm_bindings/openai/__init__.py,sha256=4Mk8eBdc9VScI0Sdh4g4p_0eU2afJeCEUEJnCQO-QkM,20014
50
50
  lollms_client/llm_bindings/openllm/__init__.py,sha256=xv2XDhJNCYe6NPnWBboDs24AQ1VJBOzsTuMcmuQ6xYY,29864
51
51
  lollms_client/llm_bindings/pythonllamacpp/__init__.py,sha256=7dM42TCGKh0eV0njNL1tc9cInhyvBRIXzN3dcy12Gl0,33551
52
52
  lollms_client/llm_bindings/tensor_rt/__init__.py,sha256=nPaNhGRd-bsG0UlYwcEqjd_UagCMEf5VEbBUW-GWu6A,32203
@@ -57,7 +57,7 @@ lollms_client/mcp_bindings/local_mcp/default_tools/file_writer/file_writer.py,sh
57
57
  lollms_client/mcp_bindings/local_mcp/default_tools/generate_image_from_prompt/generate_image_from_prompt.py,sha256=THtZsMxNnXZiBdkwoBlfbWY2C5hhDdmPtnM-8cSKN6s,9488
58
58
  lollms_client/mcp_bindings/local_mcp/default_tools/internet_search/internet_search.py,sha256=PLC31-D04QKTOTb1uuCHnrAlpysQjsk89yIJngK0VGc,4586
59
59
  lollms_client/mcp_bindings/local_mcp/default_tools/python_interpreter/python_interpreter.py,sha256=McDCBVoVrMDYgU7EYtyOY7mCk1uEeTea0PSD69QqDsQ,6228
60
- lollms_client/mcp_bindings/remote_mcp/__init__.py,sha256=NBhmk9g9iMrzoraxbQo7wacUTTB1a_azZekuRPS8SO8,16606
60
+ lollms_client/mcp_bindings/remote_mcp/__init__.py,sha256=6ebENOqO-oUk3IpitVyiMGRICSl_X5DKKaGG52BdiT8,20388
61
61
  lollms_client/mcp_bindings/standard_mcp/__init__.py,sha256=zpF4h8cTUxoERI-xcVjmS_V772LK0V4jegjz2k1PK98,31658
62
62
  lollms_client/stt_bindings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  lollms_client/stt_bindings/lollms/__init__.py,sha256=jBz3285atdPRqQe9ZRrb-AvjqKRB4f8tjLXjma0DLfE,6082
@@ -79,8 +79,8 @@ lollms_client/tts_bindings/piper_tts/__init__.py,sha256=0IEWG4zH3_sOkSb9WbZzkeV5
79
79
  lollms_client/tts_bindings/xtts/__init__.py,sha256=FgcdUH06X6ZR806WQe5ixaYx0QoxtAcOgYo87a2qxYc,18266
80
80
  lollms_client/ttv_bindings/__init__.py,sha256=UZ8o2izQOJLQgtZ1D1cXoNST7rzqW22rL2Vufc7ddRc,3141
81
81
  lollms_client/ttv_bindings/lollms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
- lollms_client-0.25.0.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
83
- lollms_client-0.25.0.dist-info/METADATA,sha256=BEfNVx_C0xdqP-26V5UbPL-mCuhtGzxsgPAEv_XveD0,13401
84
- lollms_client-0.25.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
85
- lollms_client-0.25.0.dist-info/top_level.txt,sha256=NI_W8S4OYZvJjb0QWMZMSIpOrYzpqwPGYaklhyWKH2w,23
86
- lollms_client-0.25.0.dist-info/RECORD,,
82
+ lollms_client-0.25.1.dist-info/licenses/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
83
+ lollms_client-0.25.1.dist-info/METADATA,sha256=4yR9ohOc_JjNnJeDRTdbzfYbKkmMpl0wbw0Y9D2P0gc,13401
84
+ lollms_client-0.25.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
85
+ lollms_client-0.25.1.dist-info/top_level.txt,sha256=NI_W8S4OYZvJjb0QWMZMSIpOrYzpqwPGYaklhyWKH2w,23
86
+ lollms_client-0.25.1.dist-info/RECORD,,