janito 3.1.0__py3-none-any.whl → 3.2.0__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.
@@ -12,8 +12,7 @@ from pathlib import Path
12
12
  from typing import Optional, List, Type
13
13
 
14
14
  from janito.plugin_system.base import Plugin, PluginMetadata
15
- from janito.tools.function_adapter import create_function_tool
16
- from janito.tools.tool_base import ToolBase
15
+ from janito.tools.tool_base import ToolBase, ToolPermissions
17
16
 
18
17
 
19
18
  class CorePlugin(Plugin):
@@ -38,12 +37,86 @@ class CorePlugin(Plugin):
38
37
  def get_tools(self) -> List[Type[ToolBase]]:
39
38
  return self._tool_classes
40
39
 
40
+ def _create_tool_class(self, func):
41
+ """Create a ToolBase class from a function."""
42
+ resolved_tool_name = getattr(func, "tool_name", func.__name__)
43
+
44
+ # Create a proper tool class with explicit parameters and documentation
45
+ import inspect
46
+ from typing import get_type_hints
47
+
48
+ func_sig = inspect.signature(func)
49
+ type_hints = get_type_hints(func)
50
+
51
+ # Build parameter definitions for the run method
52
+ param_defs = []
53
+ param_docs = []
54
+ for name, param in func_sig.parameters.items():
55
+ type_hint = type_hints.get(name, str)
56
+ if param.default == inspect.Parameter.empty:
57
+ param_defs.append(f"{name}: {type_hint.__name__}")
58
+ else:
59
+ param_defs.append(f"{name}: {type_hint.__name__} = {repr(param.default)}")
60
+
61
+ # Add parameter documentation
62
+ param_docs.append(f" {name}: {type_hint.__name__} - Parameter {name}")
63
+
64
+ # Get function docstring or create one
65
+ func_doc = func.__doc__ or f"Execute {resolved_tool_name} tool"
66
+
67
+ # Create the tool class with proper signature and documentation
68
+ exec_globals = {
69
+ 'ToolBase': ToolBase,
70
+ 'ToolPermissions': ToolPermissions,
71
+ 'func': func,
72
+ 'inspect': inspect,
73
+ 'str': str,
74
+ }
75
+
76
+ param_docs_str = '\n'.join(param_docs)
77
+
78
+ class_def = f'''
79
+ class DynamicTool(ToolBase):
80
+ """
81
+ {func_doc}
82
+
83
+ Parameters:
84
+ {param_docs_str}
85
+
86
+ Returns:
87
+ str: Execution result
88
+ """
89
+ tool_name = "{resolved_tool_name}"
90
+ permissions = ToolPermissions(read=True, write=True, execute=True)
91
+
92
+ def __init__(self):
93
+ super().__init__()
94
+
95
+ def run(self, {', '.join(param_defs)}) -> str:
96
+ kwargs = locals()
97
+ sig = inspect.signature(func)
98
+
99
+ # Filter kwargs to only include parameters the function accepts
100
+ filtered_kwargs = {{}}
101
+ for name, param in sig.parameters.items():
102
+ if name in kwargs and kwargs[name] is not None:
103
+ filtered_kwargs[name] = kwargs[name]
104
+
105
+ result = func(**filtered_kwargs)
106
+ return str(result) if result is not None else ""
107
+ '''
108
+
109
+ exec(class_def, exec_globals)
110
+ return exec_globals['DynamicTool']
111
+
112
+ return DynamicTool
113
+
41
114
  def initialize(self):
42
115
  """Initialize by creating tool classes."""
43
116
  self._tool_classes = []
44
117
  for tool_func in self._tools:
45
118
  if callable(tool_func):
46
- tool_class = create_function_tool(tool_func)
119
+ tool_class = self._create_tool_class(tool_func)
47
120
  self._tool_classes.append(tool_class)
48
121
 
49
122
 
@@ -11,8 +11,7 @@ from pathlib import Path
11
11
  from typing import Optional, List, Type
12
12
 
13
13
  from janito.plugin_system.base import Plugin, PluginMetadata
14
- from janito.tools.function_adapter import create_function_tool
15
- from janito.tools.tool_base import ToolBase
14
+ from janito.tools.tool_base import ToolBase, ToolPermissions
16
15
 
17
16
 
18
17
  class CorePlugin(Plugin):
@@ -37,12 +36,89 @@ class CorePlugin(Plugin):
37
36
  def get_tools(self) -> List[Type[ToolBase]]:
38
37
  return self._tool_classes
39
38
 
39
+ def _create_tool_class(self, func):
40
+ """Create a ToolBase class from a function."""
41
+ resolved_tool_name = getattr(func, "tool_name", func.__name__)
42
+
43
+ # Create a proper tool class with explicit parameters and documentation
44
+ import inspect
45
+ from typing import get_type_hints
46
+
47
+ func_sig = inspect.signature(func)
48
+ type_hints = get_type_hints(func)
49
+
50
+ # Build parameter definitions for the run method
51
+ param_defs = []
52
+ param_docs = []
53
+ for name, param in func_sig.parameters.items():
54
+ type_hint = type_hints.get(name, str)
55
+ if param.default == inspect.Parameter.empty:
56
+ param_defs.append(f"{name}: {type_hint.__name__}")
57
+ else:
58
+ param_defs.append(f"{name}: {type_hint.__name__} = {repr(param.default)}")
59
+
60
+ # Add parameter documentation
61
+ param_docs.append(f" {name}: {type_hint.__name__} - Parameter {name}")
62
+
63
+ # Get function docstring or create one
64
+ func_doc = func.__doc__ or f"Execute {resolved_tool_name} tool"
65
+
66
+ # Create the tool class with proper signature and documentation
67
+ exec_globals = {
68
+ 'ToolBase': ToolBase,
69
+ 'ToolPermissions': ToolPermissions,
70
+ 'func': func,
71
+ 'inspect': inspect,
72
+ 'str': str,
73
+ 'List': list,
74
+ 'Dict': dict,
75
+ 'Optional': type(None),
76
+ }
77
+
78
+ param_docs_str = '\n'.join(param_docs)
79
+
80
+ class_def = f'''
81
+ class DynamicTool(ToolBase):
82
+ """
83
+ {func_doc}
84
+
85
+ Parameters:
86
+ {param_docs_str}
87
+
88
+ Returns:
89
+ str: Execution result
90
+ """
91
+ tool_name = "{resolved_tool_name}"
92
+ permissions = ToolPermissions(read=True, write=True, execute=True)
93
+
94
+ def __init__(self):
95
+ super().__init__()
96
+
97
+ def run(self, {', '.join(param_defs)}) -> str:
98
+ kwargs = locals()
99
+ sig = inspect.signature(func)
100
+
101
+ # Filter kwargs to only include parameters the function accepts
102
+ filtered_kwargs = {{}}
103
+ for name, param in sig.parameters.items():
104
+ if name in kwargs and kwargs[name] is not None:
105
+ filtered_kwargs[name] = kwargs[name]
106
+
107
+ result = func(**filtered_kwargs)
108
+ return str(result) if result is not None else ""
109
+ '''
110
+
111
+ exec(class_def, exec_globals)
112
+ return exec_globals['DynamicTool']
113
+
114
+ return DynamicTool
115
+
40
116
  def initialize(self):
41
117
  """Initialize by creating tool classes."""
42
118
  self._tool_classes = []
43
119
  for tool_func in self._tools:
44
120
  if callable(tool_func):
45
- tool_class = create_function_tool(tool_func)
121
+ tool_class = self._create_tool_class(tool_func)
46
122
  self._tool_classes.append(tool_class)
47
123
 
48
124
 
@@ -13,7 +13,7 @@ from janito.plugins.discovery import list_available_plugins
13
13
  # List of core plugins that should be enabled by default
14
14
  CORE_PLUGINS = [
15
15
  "core.filemanager",
16
- "core.codeanalyzer",
16
+ "core.codeanalyzer",
17
17
  "core.system",
18
18
  "core.imagedisplay",
19
19
  "dev.pythondev",
@@ -26,23 +26,23 @@ CORE_PLUGINS = [
26
26
  def load_core_plugins(pm: PluginManager = None) -> List[str]:
27
27
  """
28
28
  Load all core plugins.
29
-
29
+
30
30
  Args:
31
31
  pm: PluginManager instance. If None, creates a new one.
32
-
32
+
33
33
  Returns:
34
34
  List of successfully loaded plugin names
35
35
  """
36
36
  if pm is None:
37
37
  pm = PluginManager()
38
-
38
+
39
39
  # Ensure plugins directory is in search path
40
40
  plugins_dir = Path.cwd() / "plugins"
41
41
  if plugins_dir.exists():
42
42
  pm.add_plugin_path(str(plugins_dir))
43
-
43
+
44
44
  loaded = []
45
-
45
+
46
46
  # Load core plugins
47
47
  for plugin_name in CORE_PLUGINS:
48
48
  try:
@@ -50,14 +50,14 @@ def load_core_plugins(pm: PluginManager = None) -> List[str]:
50
50
  loaded.append(plugin_name)
51
51
  except Exception as e:
52
52
  print(f"Warning: Failed to load core plugin {plugin_name}: {e}")
53
-
53
+
54
54
  return loaded
55
55
 
56
56
 
57
57
  def get_loaded_core_plugins() -> List[str]:
58
58
  """
59
59
  Get list of currently loaded core plugins.
60
-
60
+
61
61
  Returns:
62
62
  List of loaded core plugin names
63
63
  """
@@ -69,10 +69,10 @@ def get_loaded_core_plugins() -> List[str]:
69
69
  def is_core_plugin(plugin_name: str) -> bool:
70
70
  """
71
71
  Check if a plugin is a core plugin.
72
-
72
+
73
73
  Args:
74
74
  plugin_name: Name of the plugin to check
75
-
75
+
76
76
  Returns:
77
77
  True if it's a core plugin
78
78
  """
@@ -82,10 +82,11 @@ def is_core_plugin(plugin_name: str) -> bool:
82
82
  # Auto-load core plugins when module is imported
83
83
  _plugin_manager = None
84
84
 
85
+
85
86
  def get_plugin_manager() -> PluginManager:
86
87
  """Get the global plugin manager with core plugins loaded."""
87
88
  global _plugin_manager
88
89
  if _plugin_manager is None:
89
90
  _plugin_manager = PluginManager()
90
91
  load_core_plugins(_plugin_manager)
91
- return _plugin_manager
92
+ return _plugin_manager
@@ -27,13 +27,13 @@ class CreateFileTool(ToolBase):
27
27
  Note: Syntax validation is automatically performed after this operation.
28
28
 
29
29
  Security: This tool includes loop protection to prevent excessive file creation operations.
30
- Maximum 5 calls per 10 seconds for the same file path.
30
+ Protection: Prevents repeated create calls for the same file path within a short window (1 allowed per 10 seconds).
31
31
  """
32
32
 
33
33
  permissions = ToolPermissions(write=True)
34
34
  tool_name = "create_file"
35
35
 
36
- @protect_against_loops(max_calls=5, time_window=10.0, key_field="path")
36
+ @protect_against_loops(max_calls=1, time_window=10.0, key_field="path")
37
37
  def run(self, path: str, content: str, overwrite: bool = False) -> str:
38
38
  path = expand_path(path)
39
39
  disp_path = display_path(path)
@@ -7,8 +7,7 @@ that use the function-based approach instead of class-based.
7
7
 
8
8
  from janito.plugin_system.base import Plugin, PluginMetadata
9
9
  from typing import List, Type
10
- from janito.tools.tool_base import ToolBase
11
- from janito.tools.function_adapter import create_function_tool
10
+ from janito.tools.tool_base import ToolBase, ToolPermissions
12
11
 
13
12
 
14
13
  class CorePluginAdapter(Plugin):
@@ -36,6 +35,83 @@ class CorePluginAdapter(Plugin):
36
35
  def get_tools(self) -> List[Type[ToolBase]]:
37
36
  return self._tool_classes
38
37
 
38
+ def _create_tool_class(self, func):
39
+ """Create a ToolBase class from a function."""
40
+ resolved_tool_name = getattr(func, "tool_name", func.__name__)
41
+
42
+ # Create a proper tool class with explicit parameters and documentation
43
+ import inspect
44
+ from typing import get_type_hints
45
+
46
+ func_sig = inspect.signature(func)
47
+ type_hints = get_type_hints(func)
48
+
49
+ # Build parameter definitions for the run method
50
+ param_defs = []
51
+ param_docs = []
52
+ for name, param in func_sig.parameters.items():
53
+ type_hint = type_hints.get(name, str)
54
+ if param.default == inspect.Parameter.empty:
55
+ param_defs.append(f"{name}: {type_hint.__name__}")
56
+ else:
57
+ param_defs.append(f"{name}: {type_hint.__name__} = {repr(param.default)}")
58
+
59
+ # Add parameter documentation
60
+ param_docs.append(f" {name}: {type_hint.__name__} - Parameter {name}")
61
+
62
+ # Get function docstring or create one
63
+ func_doc = func.__doc__ or f"Execute {resolved_tool_name} tool"
64
+
65
+ # Create the tool class with proper signature and documentation
66
+ exec_globals = {
67
+ 'ToolBase': ToolBase,
68
+ 'ToolPermissions': ToolPermissions,
69
+ 'func': func,
70
+ 'inspect': inspect,
71
+ 'str': str,
72
+ 'List': list,
73
+ 'Dict': dict,
74
+ 'Optional': type(None),
75
+ }
76
+
77
+ param_docs_str = '\n'.join(param_docs)
78
+
79
+ class_def = f'''
80
+ class DynamicTool(ToolBase):
81
+ """
82
+ {func_doc}
83
+
84
+ Parameters:
85
+ {param_docs_str}
86
+
87
+ Returns:
88
+ str: Execution result
89
+ """
90
+ tool_name = "{resolved_tool_name}"
91
+ permissions = ToolPermissions(read=True, write=True, execute=True)
92
+
93
+ def __init__(self):
94
+ super().__init__()
95
+
96
+ def run(self, {', '.join(param_defs)}) -> str:
97
+ kwargs = locals()
98
+ sig = inspect.signature(func)
99
+
100
+ # Filter kwargs to only include parameters the function accepts
101
+ filtered_kwargs = {{}}
102
+ for name, param in sig.parameters.items():
103
+ if name in kwargs and kwargs[name] is not None:
104
+ filtered_kwargs[name] = kwargs[name]
105
+
106
+ result = func(**filtered_kwargs)
107
+ return str(result) if result is not None else ""
108
+ '''
109
+
110
+ exec(class_def, exec_globals)
111
+ return exec_globals['DynamicTool']
112
+
113
+ return DynamicTool
114
+
39
115
  def initialize(self):
40
116
  """Initialize the plugin by creating tool classes."""
41
117
  # Get tools from the module
@@ -44,7 +120,7 @@ class CorePluginAdapter(Plugin):
44
120
  self._tool_classes = []
45
121
  for tool_func in tools:
46
122
  if callable(tool_func):
47
- tool_class = create_function_tool(tool_func)
123
+ tool_class = self._create_tool_class(tool_func)
48
124
  self._tool_classes.append(tool_class)
49
125
 
50
126
 
@@ -17,11 +17,11 @@ from .core_adapter import CorePluginAdapter
17
17
  def _load_core_plugin(package_path: Path, plugin_name: str) -> Optional[Plugin]:
18
18
  """
19
19
  Load a core plugin from a package directory.
20
-
20
+
21
21
  Args:
22
22
  package_path: Path to the __init__.py file
23
23
  plugin_name: Full plugin name (e.g., core.filemanager)
24
-
24
+
25
25
  Returns:
26
26
  Plugin instance if loaded successfully
27
27
  """
@@ -30,20 +30,25 @@ def _load_core_plugin(package_path: Path, plugin_name: str) -> Optional[Plugin]:
30
30
  spec = importlib.util.spec_from_file_location(plugin_name, package_path)
31
31
  if spec is None or spec.loader is None:
32
32
  return None
33
-
33
+
34
34
  module = importlib.util.module_from_spec(spec)
35
35
  spec.loader.exec_module(module)
36
-
36
+
37
37
  # Get plugin metadata
38
38
  plugin_name_attr = getattr(module, "__plugin_name__", plugin_name)
39
- description = getattr(module, "__plugin_description__", f"Core plugin: {plugin_name}")
40
-
39
+ description = getattr(
40
+ module, "__plugin_description__", f"Core plugin: {plugin_name}"
41
+ )
42
+
41
43
  # Create and return the core plugin adapter
42
44
  plugin = CorePluginAdapter(plugin_name_attr, description, module)
43
45
  plugin.initialize() # Initialize to set up tools
44
46
  return plugin
45
-
47
+
46
48
  except Exception as e:
47
49
  import logging
48
- logging.getLogger(__name__).error(f"Failed to load core plugin {plugin_name}: {e}")
49
- return None
50
+
51
+ logging.getLogger(__name__).error(
52
+ f"Failed to load core plugin {plugin_name}: {e}"
53
+ )
54
+ return None
@@ -6,16 +6,6 @@ from functools import wraps
6
6
  from typing import Type
7
7
  from janito.plugin_system.base import Plugin, PluginMetadata
8
8
 
9
- # Registry for core tools
10
- _core_tools_registry = []
11
-
12
-
13
- def register_core_tool(cls: Type):
14
- """Decorator to register a core tool."""
15
- _core_tools_registry.append(cls)
16
- return cls
17
-
18
-
19
9
  from .ask_user import AskUser
20
10
  from .copy_file import CopyFile
21
11
  from .create_directory import CreateDirectory
@@ -44,6 +34,15 @@ from .get_file_outline.core import GetFileOutline
44
34
  from .search_text.core import SearchText
45
35
  from .decorators import get_core_tools
46
36
 
37
+ # Registry for core tools
38
+ _core_tools_registry = []
39
+
40
+
41
+ def register_core_tool(cls: Type):
42
+ """Decorator to register a core tool."""
43
+ _core_tools_registry.append(cls)
44
+ return cls
45
+
47
46
 
48
47
  class CoreToolsPlugin(Plugin):
49
48
  """Core tools plugin providing essential janito functionality."""
@@ -55,7 +55,7 @@ class CreateFile(ToolBase):
55
55
  or file exists (when overwrite=False).
56
56
 
57
57
  Security Features:
58
- - Loop protection: Maximum 5 calls per 10 seconds for the same file path
58
+ - Loop protection: Prevents repeated create calls for the same file path within a short window (1 allowed per 10 seconds)
59
59
  - Path traversal prevention: Validates and sanitizes file paths
60
60
  - Permission checking: Respects file system permissions
61
61
  - Atomic writes: Prevents partial file creation on errors
@@ -84,7 +84,7 @@ class CreateFile(ToolBase):
84
84
  permissions = ToolPermissions(write=True)
85
85
  tool_name = "create_file"
86
86
 
87
- @protect_against_loops(max_calls=5, time_window=10.0, key_field="path")
87
+ @protect_against_loops(max_calls=1, time_window=10.0, key_field="path")
88
88
  def run(self, path: str, content: str, overwrite: bool = False) -> str:
89
89
  path = expand_path(path)
90
90
  disp_path = display_path(path)
@@ -10,3 +10,4 @@ import janito.providers.zai.provider
10
10
  import janito.providers.cerebras.provider
11
11
  import janito.providers.mistral.provider
12
12
  import janito.providers.ibm.provider
13
+ import janito.providers.together.provider
@@ -0,0 +1 @@
1
+ # Together AI provider for Janito
@@ -0,0 +1,69 @@
1
+ """
2
+ Model specifications for Together AI provider.
3
+ """
4
+
5
+ MODEL_SPECS = {
6
+ "allenai/OLMo-2-0325-32B-Instruct": {
7
+ "max_tokens": 32768,
8
+ "max_input_tokens": 32768,
9
+ "max_output_tokens": 32768,
10
+ "description": "OLMo 2 32B Instruct - Fully open language model from AllenAI",
11
+ "supports_tools": True,
12
+ "supports_system_prompt": True,
13
+ "supports_streaming": True,
14
+ },
15
+ "allenai/OLMo-2-1124-7B-Instruct": {
16
+ "max_tokens": 32768,
17
+ "max_input_tokens": 32768,
18
+ "max_output_tokens": 32768,
19
+ "description": "OLMo 2 7B Instruct - Fully open language model from AllenAI",
20
+ "supports_tools": True,
21
+ "supports_system_prompt": True,
22
+ "supports_streaming": True,
23
+ },
24
+ "allenai/OLMo-2-0425-1B": {
25
+ "max_tokens": 32768,
26
+ "max_input_tokens": 32768,
27
+ "max_output_tokens": 32768,
28
+ "description": "OLMo 2 1B - Fully open language model from AllenAI",
29
+ "supports_tools": True,
30
+ "supports_system_prompt": True,
31
+ "supports_streaming": True,
32
+ },
33
+ "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo": {
34
+ "max_tokens": 8192,
35
+ "max_input_tokens": 128000,
36
+ "max_output_tokens": 8192,
37
+ "description": "Llama 3.1 8B Instruct Turbo",
38
+ "supports_tools": True,
39
+ "supports_system_prompt": True,
40
+ "supports_streaming": True,
41
+ },
42
+ "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo": {
43
+ "max_tokens": 8192,
44
+ "max_input_tokens": 128000,
45
+ "max_output_tokens": 8192,
46
+ "description": "Llama 3.1 70B Instruct Turbo",
47
+ "supports_tools": True,
48
+ "supports_system_prompt": True,
49
+ "supports_streaming": True,
50
+ },
51
+ "mistralai/Mixtral-8x7B-Instruct-v0.1": {
52
+ "max_tokens": 32768,
53
+ "max_input_tokens": 32768,
54
+ "max_output_tokens": 32768,
55
+ "description": "Mixtral 8x7B Instruct",
56
+ "supports_tools": True,
57
+ "supports_system_prompt": True,
58
+ "supports_streaming": True,
59
+ },
60
+ "deepseek-ai/deepseek-llm-67b-chat": {
61
+ "max_tokens": 4096,
62
+ "max_input_tokens": 4096,
63
+ "max_output_tokens": 4096,
64
+ "description": "DeepSeek LLM 67B Chat",
65
+ "supports_tools": True,
66
+ "supports_system_prompt": True,
67
+ "supports_streaming": True,
68
+ },
69
+ }
@@ -0,0 +1,108 @@
1
+ from janito.llm.provider import LLMProvider
2
+ from janito.llm.model import LLMModelInfo
3
+ from janito.llm.auth import LLMAuthManager
4
+ from janito.llm.driver_config import LLMDriverConfig
5
+ from janito.drivers.openai.driver import OpenAIModelDriver
6
+ from janito.tools import get_local_tools_adapter
7
+ from janito.providers.registry import LLMProviderRegistry
8
+ from .model_info import MODEL_SPECS
9
+ from queue import Queue
10
+
11
+ available = OpenAIModelDriver.available
12
+ unavailable_reason = OpenAIModelDriver.unavailable_reason
13
+
14
+
15
+ class TogetherProvider(LLMProvider):
16
+ name = 'together'
17
+ NAME = 'together'
18
+ MAINTAINER = 'Janito Team'
19
+ MODEL_SPECS = MODEL_SPECS
20
+ DEFAULT_MODEL = 'allenai/OLMo-2-0325-32B-Instruct'
21
+
22
+ def __init__(
23
+ self, auth_manager: LLMAuthManager = None, config: LLMDriverConfig = None
24
+ ):
25
+ self._tools_adapter = get_local_tools_adapter()
26
+ self._driver = None
27
+
28
+ if not self.available:
29
+ return
30
+
31
+ self._initialize_config(auth_manager, config)
32
+ self._setup_model_config()
33
+
34
+ def _initialize_config(self, auth_manager, config):
35
+ self.auth_manager = auth_manager or LLMAuthManager()
36
+ self._api_key = self.auth_manager.get_credentials(type(self).NAME)
37
+ if not self._api_key:
38
+ from janito.llm.auth_utils import handle_missing_api_key
39
+ handle_missing_api_key(self.name, 'TOGETHER_API_KEY')
40
+
41
+ self._driver_config = config or LLMDriverConfig(model=None)
42
+ if not self._driver_config.model:
43
+ self._driver_config.model = self.DEFAULT_MODEL
44
+ if not self._driver_config.api_key:
45
+ self._driver_config.api_key = self._api_key
46
+
47
+ self._driver_config.base_url = 'https://api.together.xyz/v1'
48
+
49
+ def _setup_model_config(self):
50
+ model_name = self._driver_config.model
51
+ model_spec = self.MODEL_SPECS.get(model_name)
52
+
53
+ if hasattr(self._driver_config, 'max_tokens'):
54
+ self._driver_config.max_tokens = None
55
+ if hasattr(self._driver_config, 'max_completion_tokens'):
56
+ self._driver_config.max_completion_tokens = None
57
+
58
+ if model_spec:
59
+ max_tokens = getattr(model_spec, 'max_tokens', None)
60
+ if max_tokens and max_tokens != 'N/A':
61
+ self._driver_config.max_tokens = int(max_tokens)
62
+
63
+ self.fill_missing_device_info(self._driver_config)
64
+
65
+ @property
66
+ def driver(self) -> OpenAIModelDriver:
67
+ if not self.available:
68
+ raise ImportError(f'TogetherProvider unavailable: {self.unavailable_reason}')
69
+ return self._driver
70
+
71
+ @property
72
+ def available(self):
73
+ return available
74
+
75
+ @property
76
+ def unavailable_reason(self):
77
+ return unavailable_reason
78
+
79
+ def create_driver(self):
80
+ driver = OpenAIModelDriver(
81
+ tools_adapter=self._tools_adapter, provider_name=self.NAME
82
+ )
83
+ driver.config = self._driver_config
84
+ return driver
85
+
86
+ def create_agent(self, tools_adapter=None, agent_name: str = None, **kwargs):
87
+ from janito.llm.agent import LLMAgent
88
+ if tools_adapter is None:
89
+ tools_adapter = get_local_tools_adapter()
90
+ raise NotImplementedError(
91
+ 'create_agent must be constructed via new factory using input/output queues and config.'
92
+ )
93
+
94
+ @property
95
+ def model_name(self):
96
+ return self._driver_config.model
97
+
98
+ @property
99
+ def driver_config(self):
100
+ return self._driver_config
101
+
102
+ def execute_tool(self, tool_name: str, event_bus, *args, **kwargs):
103
+ self._tools_adapter.event_bus = event_bus
104
+ return self._tools_adapter.execute_by_name(tool_name, *args, **kwargs)
105
+
106
+
107
+ LLMProviderRegistry.register(TogetherProvider.NAME, TogetherProvider)
108
+